05月28, 2020

发布-订阅模式的通用实现

const eventEmitter = {
  list: [], // {1}
  on: function( key, fn ){ // {2}
    if ( !this.list[ key ] ){
      this.list[ key ] = [];
    }
    this.list[ key ].push( fn );    // 订阅的消息添加进缓存列表
  },
  emit: function(){ // {3}
    const key = Array.prototype.shift.call( arguments ),    // 获取传入的第一个参数
      fns = this.list[ key ]; // 通过key获取到相应的事件集合

    if ( !fns || fns.length === 0 ){
      return false;
    }

    for( let i = 0; i<fns.length; i++ ){
      fns[i].apply( this, arguments );    // 调用相应订阅函数
    }
  },
  remove : function( key, fn ){ // {4}
    const fns = this.list[ key ];

    if ( !fns ){    // 如果key对应的消息没有被人订阅,则直接返回
      return false;
    }
    if ( !fn ){    // 如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
      fns && ( fns.length = 0 );
    }else{
      for ( let l = fns.length - 1; l >=0; l-- ){    // 反向遍历订阅的回调函数列表
        let _fn = fns[ l ];
        if ( _fn === fn ){
          fns.splice( l, 1 );    // 删除订阅者的回调函数
        }
      }
    }
  }
};

代码解释:

  • {1} list 数组用来存储订阅数据
  • {2} on 用来订阅事件
  • {3} emit 用来发布事件
  • {4} remove 删除相关订阅

function user1 (content) { console.log('用户1订阅了:', content); }

function user2 (content) { console.log('用户2订阅了:', content); }

eventEmitter.on("订阅事件A",user1); eventEmitter.on("订阅事件A",user2);

eventEmitter.emit("订阅事件A","哈哈");

17258ab378664b88.jpg

发布—订阅模式的优点非常明显,一为时间上的解耦,二为对象之间的解耦。它的应用非常广泛,既可以用在异步编程中,也可以帮助我们完成更松耦合的代码编写。 从架构上来看,无论是MVC还是MVVM(vue.js),都少不了发布—订阅模式的参与,而且JavaScript本身也是一门基于事件驱动的语言。

作者:小小LION 链接:https://juejin.im/post/5ecf04ace51d45786d3fda70 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文链接:https://blog.hijs.cc/post/fa-bu---ding-yue-mo-shi-de-tong-yong-shi-xian.html

-- EOF --

Comments