js:发布-订阅模式

发布-订阅模式
定义对象间一对多的依赖关系,当一个对象状态改变将使所有依赖它的对象获得通知。
与直接使用回调函数一样实现异步通信,但可较方便的实现同一事件响应的多个响应者的管理,降低触发者和响应者的耦合。
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曾探,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值