js:リリース-購読モード

6931 ワード

リリース・購読モードは、オブジェクト間の1対以上の依存関係を定義し、オブジェクトの状態が変化すると、すべてのオブジェクトに依存して通知が得られます.非同期通信は、コールバック関数を直接使用するように実現されるが、同じイベント応答を実装する複数の応答者の管理がより便利であり、トリガと応答者の結合を低減する.DOMイベントの傍受は、リリース・購読モードの実現である.
    //       -    
    (function(win){
      //   -        
      var event = {
        listenTypes: []
        ,listen: function( type, fn ){
          //       type   
          if (!this.listenTypes[type]){
            this.listenTypes[type] = [];
          }
          //    type           
          this.listenTypes[type].push(fn);
        }
        ,trigger: function(){
          var type = Array.prototype.shift.call( arguments ),
            callFns = this.listenTypes[type],
            fn = null;
          //         
          if (!callFns || callFns.length === 0){
            return false;
          }
          //           
          for (var i in callFns){
            fn = callFns[i];
            fn.apply(this, arguments);
          }
        }
        ,remove: function( type, fn ){
          var callFns = this.listenTypes[type];
          //        ,    
          if(!callFns){
            return true;
          }
          //      type,           ,       
          if(!fn){
            console.log("    " + type + "    。");
            callFns = [];
          }else{
            var tempFn = null;
            for(var j=callFns.length-1; j>=0; j--){
              tempFn = callFns[ j ];
              if(tempFn === fn){
                //          
                callFns.splice( j, 1 );
              }
            }
          }
        }
      };
      //                
      var installEvent = (function(){
        return function(obj){
          for (var i in event){
            obj[ i ] = event[ i ];
          }
        };
      })();

      win.installEvent = installEvent;
    })(window);

    //   A
    var userA = {
      name: "User A"
      ,getMsg: function(msg){
        console.log(this.name + " get message: " + msg);
      }
    };
    //   B
    var userB = {
      name: "User B"
      ,getMsg: function(msg){
        console.log(this.name + " get message: " + msg);
      }
    };

    //    
    var server = {
      msgA: "      "
      ,msgB: "      "
    }
    //       
    installEvent(server);
    //   A   
    var fn_A = userA.getMsg.bind(userA);
    //   B   
    var fn_B = userA.getMsg.bind(userB);

    server.listen("planA", fn_A );
    server.listen("planB", fn_A );
    server.listen("planB", fn_B );

    //    "planA"   
    console.log("   planA   ");
    server.trigger("planA", server.msgA);

    //    "planB"   
    console.log("   planB   ");
    server.trigger("planB", server.msgB);

    //     A   "planB"   
    server.remove("planB", fn_A );
    //    "planB"   
    console.log("   planB   ");
    server.trigger("planB", server.msgB);

    /*    :
       planA   
    User A get message:       
       planB   
    User A get message:       
    User B get message:       
       planB   
    User B get message:       
    */
一部のコードの引用と修正:「JavaScript設計モードと実践」byかつて探ったことがあります.