pub/sub的實際應用總結

看風景就發表於2017-12-29

pub/sub即觀察者模式,有多重表現形式

1. Publisher/Subscriber
2. Observer/Observable
3. Listener(例如EventListener)
4. EventBus
5. EventEmitter

EventBus這種不只是觀察者模式,還包含了中介者模式,bus就是一箇中介者,負責在消費者和生產者之間轉發訊息
而Observer/Observable則是一種比較純粹的觀察者模式,一個物件要釋出訊息時候,就可以暴露一個Observable出來,
一個想要接收訊息,找到這個Observalble並且Subscribe它。

下面總結常用框架自帶的pub/sub模式實現

1. jquery的Pub/Sub實現

1.1 直接註冊事件的方法進行

例如,在window上註冊自定義事件,由於jquery是事件支援名稱空間,對pub/sub的支援更加給力。

$(window).on('topic.eventType',function(event,data){

});

$(window).trigger('topic.eventType',[data]);

1.2 使用jquery的callbacks函式

jquery自帶的callbacks系列函式,就是一個優質的pub/sub的實現,直接使用即可。

var topic = $.Callbacks();
topic.add(function () { ... });
topic.fire();

也可以進行簡單的封裝,使其更加自然:

var topics = {};
 
jQuery.Topic = function( id ) {
  var callbacks, method,
    topic = id && topics[ id ];
 
  if ( !topic ) {
    callbacks = jQuery.Callbacks();
    topic = {
      publish: callbacks.fire,
      subscribe: callbacks.add,
      unsubscribe: callbacks.remove
    };
    if ( id ) {
      topics[ id ] = topic;
    }
  }
  return topic;
};

// Subscribers
$.Topic( "mailArrived" ).subscribe( fn1 );
$.Topic( "mailArrived" ).subscribe( fn2 );
$.Topic( "mailSent" ).subscribe( fn1 );
 
// Publisher
$.Topic( "mailArrived" ).publish( "hello world!" );
$.Topic( "mailSent" ).publish( "woo! mail!" );

具體可以參考 http://api.jquery.com/jQuery.Callbacks/

2.vue的Pub/Sub實現

由於vue例項可以監聽和釋出事件,其可以充當一個EventBus,就可以直接實現一個pub/sub的應用

var bus = new Vue();
bus.$on('evnetType',function(data){

});
bus.$emit('evnetType',data);

具體在vue元件中使用時候,要在元件銷燬時解綁事件。

created() {
  this.$bus.$on('evnet1', this.method1);
  this.$bus.$on('evnet2', this.method2);
},
// 清除事件監聽
beforeDestroy () {
  this.$bus.$off('evnet1', this.method1);
  this.$bus.$off('evnet2', this.method2);
}

當然也可以使用第三方的bus實現,省去解除繫結和使用具名函式的麻煩,例如vue-happy-bus。
bus模式只是適用於簡單的元件通訊,複雜的通訊還是使用vuex吧

3.Node.js的Pub/Sub實現

EventEmitter

emitter.on(event, listener) //註冊一個事件

emitter.once(event, listener) //註冊一個一次性的事件,觸發後就被抹掉

emitter.removeListener(event, listener) //在時間佇列中剔除某一個事件

emitter.removeAllListeners([event]) //刪除整個事件佇列,或多個事件

emitter.listeners(event) //返回某些事件 

emitter.emit(event, [arg1], [arg2], […]) //觸發事件,可傳入具體引數

在需要一些Pub/Sub實現,例如動畫的執行時機在一個介面執行完之後,又需要在一個按鈕點選之後,只是少量情況,但是又有需求,這種場合就非常合適。用框架自帶的實現,省去了引入第三方包的麻煩。

 

相關文章