理解並實現PubSub模式


假如我們正在構建一個類似於 Google Docs 的應用程序,當用戶按下一個按鍵時,需要做的事情有很多: 新字符顯示到屏幕上;插入點向后移動;將本次動作加入到撤銷的歷史記錄中; 保持與服務器同步;拼寫錯誤檢查;統計字數和頁數等等。

按照傳統的做法,假如我們監聽 keypress 事件,並在一個處理中完成所有的任務,這想想都覺得可怕了。 那么有沒有什么方法可以更好的解決這個問題,答案就是分布式事件

PubSub 模式,是 Publish/Subscribe 的縮寫,意為“發布/訂閱”模式。

在實際使用中,我們應該也會接觸到 PubSub 模式,例如 Nodejs 中的 EventEmitter、Backbone 中的事件模型、以及 jQuery 中的事件。 以 EventEmitter 為栗子,它提供了 addListener(event, listener),removeListener(event, listener),emit(event, [arg1], [arg2], [...]) 方法。

var emitter = new EventEmitter(), fn1 = function(value) { console.log('fn1:', value); }, fn2 = function(value) { console.log('fn2:', value); }; emitter.addListener('message', fn1); emitter.addListener('message', fn2); emitter.emit('message', 'test1'); emitter.removeListener('message', fn2); emitter.emit('message', 'test2'); //fn1: test1 //fn2: test1 //fn1: test2 

當調用 emit 方法時,會觸發所有監聽的事件。

就像上面說的,PubSub 其實很簡單,現在我們來實現屬於我們自己的 PubSub 對象。

首先創建 PubSub 類,增加 handlers 變量用於保存事件列表:

function PubSub() { this.handlers = {}; } 

添加事件時,將監聽器加到數組中:

PubSub.prototype.on = function(type, listener) { if (!(type in this.handlers)) { this.handlers[type] = []; } this.handlers[type].push(listener); }; 

刪除事件時,移除監聽器:

PubSub.prototype.off = function(type, listener) { var i, position = -1, list = this.handlers[type], length = this.handlers[type].length; for (i = 0; i < length; i++) { if (list[i] === listener) { position = i; break; } } if (position === -1) { return; } if (length === 1) { delete this.handlers[type]; } else { this.handlers[type].splice(position, 1); } }; 

觸發事件,循環遍歷並觸發所有的事件:

PubSub.prototype.emit = function(type) {
    var args = Array.prototype.slice.call(arguments, 1), i, list = this.handlers[type], length = this.handlers[type].length; for (i = 0; i < length; i++) { list[i].apply(this, args); } }; 

測試:

var pubsub = new PubSub(), fn1 = function(value) { console.log('fn1:', value); }, fn2 = function(value) { console.log('fn2:', value); }; pubsub.on('message', fn1); pubsub.on('message', fn2); pubsub.emit('message', 'test1'); pubsub.off('message', fn2); pubsub.emit('message', 'test2'); //fn1: test1 //fn2: test1 //fn1: test2 

注:更多的實現請看 Nodejs 中的 events.js

轉自:http://www.wenzhixin.net.cn/2013/11/06/understand_pubsub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM