JavaScript 디자인 모드의 게시 구독 모드(Publish/Subscribe)

5445 단어
게시/구독 모드는 관찰자 모드라고도 부른다. 대상 간의 일대다 의존 관계를 정의하고 한 대상의 상태가 바뀌면 모든 의존 대상이 알림을 받는다.JavaScript 개발에서, 우리는 일반적으로 이벤트 모델로 전통적인 게시/구독 모델을 대체한다.

도처에서 게시 구독 현상


오늘날의 정보화 시대에 발표/구독 모델의 응용은 매우 광범위하다고 할 수 있다. 예를 들어 위챗 공중번호는 전형적인 발표/구독 모델이고 공중번호가 정보를 발표하면 모든 구독자가 받을 수 있다.
누군가는 자주 받는 각종 광고 문자 메시지(수동 구독일 수도 있음)를 생각할 수도 있지만, 사실 문자 메시지나 광고를 보내는 것도 전형적인 게시/구독 모델이다.
게시/구독 모드는 비동기 프로그래밍에서 함수를 전달하는 방안을 대체할 수 있습니다. 예를 들어, 우리는 aax가 요청한 error,succ 등 이벤트를 구독할 수 있습니다.
또한 구독 발표는 두 대상을 느슨하게 결합시켜 서로의 세부 사항을 알 필요가 없고 새로운 구독자가 나타날 때 발표자의 코드는 아무런 수정도 필요 없다.같은 게시자가 바뀌어야 할 때도 이전 구독자에게 영향을 주지 않는다.기존에 약속한 사건명에 변화가 없으면 자유롭게 바꿀 수 있다.

정의


게시 구독 모드는 한 쌍의 여러 관계를 정의하여 여러 관찰자 대상이 특정한 주제 대상을 동시에 감청하도록 한다. 이 주제 대상의 상태가 변할 때 모든 관찰자 대상에게 통지하여 자신을 자동으로 업데이트할 수 있도록 한다.
게시 구독 모드를 사용하면 다음과 같은 이점이 있습니다.
  • 간단한 방송 통신을 지원하여 이미 구독한 모든 대상을 자동으로 알린다.
  • 페이지를 불러온 후 목표 대상은 관찰자와 동적 관련이 존재하기 쉬워 유연성을 증가시켰다.
  • 목표 대상과 관찰자 간의 추상적 결합 관계는 단독으로 확장되고 중용될 수 있다.

  • 인스턴스 사용


    게시 구독 사용자 정의


    사용자 정의 게시 구독 모드를 시도해 보겠습니다. 어떻게 게시 구독을 실현할 수 있을까요?
  • 게시자 지정
  • 게시자에게 버퍼 목록을 추가하여 구독자에게 알릴 수 있는 리셋 함수를 저장합니다
  • 메시지를 발표할 때 발표자는 캐시 목록을 훑어보고 각 구독자의 리셋 함수
  • 를 순서대로 터치한다.
    간단한 날씨 상태 구독
    var Weather = {
        list: [], //  
        listen: function(fn) { //    
            this.list.push(fn)
        },
        publish: function() { //  
            for(var i=0,fn; fn=this.list[i++];) {
                fn.apply(this,arguments);
            }
        }
    };
    
    //  
    Weather.listen(function(weather, wind){
        console.log(' :' + weather, ' :'+ wind);
    })
    
    //  
    Weather.publish(" "," "); //  :   : 
    Weather.publish(" ","5 "); //  :   :5 
    

    지금까지 가장 간단한 게시 - 구독 모드를 실현했고 구독자에게 선택 기능을 추가하여 자신이 원하는 정보를 구독할 수도 있고 구독 취소 이벤트를 추가할 수도 있다.
    var PubSub = {
        list: [],
        listen: function(key, fn){
            if(!this.list[key]) {
                this.list[key]=[];
            }
            this.list[key].push(fn);
        },
        publish: function(){
            var key = Array.prototype.shift.call(arguments),
                fns = this.list[key];
            if(!fns || fns.length === 0) {
                return false;
            }
            for(var i = 0, fn; fn = fns[i++];){
                fn.apply(this, arguments);
            }
        }
    }
    
    //
    var installEvent = function(obj) {
        for (var i in PubSub) {
            obj[i] = PubSub[i];
        }
    };
    
    var day = {}
    installEvent(day);
    
    day.listen(' ', function(wind) {
        console.log(' :'+ wind);
    });
    
    day.publish(' ', "8 ");
    

    실전의 사이트 로그인


    사이트 로그인은 가장 흔히 볼 수 있는 형식으로 로그인한 후에 우리는ajax에서 사용자 정보를 요청한다. 예를 들어 사용자 이름, 이미지 등 정보를 헤더 모듈에 표시하는데 이 두 필드는 모두 사용자가 로그인한 후에 되돌아오는 정보이다.aax 요청이 언제 사용자 정보를 되돌릴 수 있는지 확인할 수 없습니다. 지금은 구독 모드를 발표하는 것과 상관없지만, 비동기적인 문제도 함수를 되돌려 해결할 수 있기 때문입니다.
    우리는 헤더 헤드, nav 내비게이션, 메시지 목록, 쇼핑 카트 외에 앞으로 어떤 모듈이 이런 사용자 정보를 사용해야 할지 모른다.만약 그것들이 사용자 정보 모듈과 강한 결합을 일으켰다면, 예를 들어 다음과 같은 형식이 있다.
    login.succ(function(data){ 
        header.setAvatar( data.avatar);  //   header  
        nav.setAvatar( data.avatar ); //  
        message.refresh(); //  
        cart.refresh(); //  
    });
    

    현재 로그인 모듈은 우리가 작성하는 것이지만 헤더 모듈에 이미지를 설정하는 방법인 set Avatar, 쇼핑 카트 모듈에 새로 고침하는 방법인refresh를 알아야 한다. 이런 결합성은 프로그램을 경직시킬 수 있다. 헤더 모듈은 set Avatar의 방법 이름을 마음대로 바꿀 수 없고 자신의 이름도 헤더 1, 헤더 2로 바꿀 수 없다.이것은 구체적으로 프로그래밍을 실현하는 전형적인 예로 구체적으로 프로그래밍을 실현하는 것은 찬성하지 않는다.
    항목에 새로 추가된 수확 주소 관리 모듈:
    login.succ(function(data){ 
        header.setAvatar( data.avatar);
        nav.setAvatar( data.avatar ); 
        message.refresh(); 
        address.refresh(); //  
    });
    

    현재 우리는 게시 구독 리셋으로 사용자 정보에 관심이 있는 업무 모듈에서 로그인에 성공한 메시지 이벤트를 스스로 구독할 것입니다.로그인에 성공할 때 로그인 모듈은 로그인에 성공했다는 소식만 발표하고 업무 측이 소식을 받은 후에 각자의 업무 처리를 시작한다. 로그인 모듈은 업무 측이 무엇을 하려는지, 그들의 내부 세부 사항을 알고 싶지 않다.개선된 코드는 다음과 같습니다.
    $.ajax( 'http://xxx.com?login', function(data){ //   
        login.trigger( 'loginSucc', data); //  
    });
    

    각 모듈에서 로그인 성공 메시지를 수신합니다.
    var header = (function() { // header  
        login.listen( 'loginSucc', function(data) {
            header.setAvatar( data.avatar );
        });
        return {
            setAvatar: function(data) {
                console.log( '  header  ');
            }
        }
    })();
    
    var nav = (function() {  // nav  
        login.listen('loginSucc', function(data) {
            nav.setAvatar( data.avatar );
        });
        return {
            setAvatar: function(avatar) {
                console.log( '  nav  ');
            }
        }
    })();
    
    

    만약에 어느 날 로그인이 완료된 후에 또 하나의 수령 주소 목록을 갱신하는 행위를 추가한다면 수령 주소 모듈에 정보를 감청하는 방법을 추가하면 된다. 이 모듈을 개발한 동료가 스스로 완성할 수 있다. 당신은 로그인 모듈의 개발자로서 이런 행위에 더 이상 관심을 갖지 않아도 된다.
    var address = (function(){ //   
        login.listen('loginSucc', function(obj){
            address.refresh(obj);
        });
        return {
            refresh: function( avatar ){
                console.log( ' ' ); 
            }
        } 
    })();
    

    총결산


    게시 구독의 사용 장소는 한 대상의 변화가 다른 대상을 동시에 바꾸어야 하고 구체적으로 얼마나 많은 대상이 바뀌어야 하는지 모르면 관찰자 모델을 고려해야 한다는 것이다.
    전체적으로 말하자면 구독 모델을 발표하는 일은 결합을 풀고 결합된 쌍방을 추상에 의존하게 하는 것이지 구체적인 것에 의존하게 하는 것이 아니다.따라서 각자의 변화가 다른 쪽의 변화에 영향을 주지 않는다.
    또한 게시 - 구독 모드는 개체 간의 연결을 약화시킬 수 있지만 과도하게 사용하면 개체와 개체 간의 필수적인 연결도 배후에 깊이 파묻혀 프로그램의 추적과 유지보수, 이해를 어렵게 할 수 있다.특히 여러 게시자와 구독자가 겹칠 때 버그를 추적하는 것은 쉬운 일이 아니다.
    참고 자료
    JavaScript 디자인 모델 및 개발 실습
    톰 아저씨의 블로그--자바스크립트 시리즈 깊이 이해

    좋은 웹페이지 즐겨찾기