成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【node不完全指西】EventEmitter (事件發(fā)布/訂閱模式)解析

yagami / 1242人閱讀

摘要:從異步編程解決方案說起吧事件發(fā)布訂閱模式模式流程控制庫事件發(fā)布訂閱模式事件監(jiān)聽器模式是一種廣泛運(yùn)用于異步編程的模式,是回調(diào)函數(shù)的事件話,又稱發(fā)布訂閱模式。

從node異步編程解決方案說起吧:

事件發(fā)布/訂閱模式

Promise/deferred模式

流程控制庫

事件發(fā)布/訂閱模式
事件監(jiān)聽器模式是一種廣泛運(yùn)用于異步編程的模式,是回調(diào)函數(shù)的事件話,又稱發(fā)布/訂閱模式。

主要實(shí)現(xiàn)的幾個(gè)功能包括

on

remove

once

emit

廢話少說,我們來簡(jiǎn)單的實(shí)現(xiàn)一個(gè)事件監(jiān)聽函數(shù)吧

首先創(chuàng)建一個(gè)eventEmitter函數(shù)
function EventEmitter() {
    // 用Object.create(null)代替空對(duì)象{}
    // 好處是無雜質(zhì),不繼承原型鏈
    // _events來保存觀察著隊(duì)列的信息
    this._events = Object.create(null);
}

因?yàn)檫^多的偵聽器占用大量?jī)?nèi)存,導(dǎo)致內(nèi)存泄漏,所以偵聽器的個(gè)數(shù)一般不會(huì)超過10個(gè),否則會(huì)有warnning警告??
接下來是一些默認(rèn)的設(shè)置

// 默認(rèn)最多的綁定次數(shù)
EventEmitter.defaultMaxListeners = 10;
// 同on方法
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
// 返回監(jiān)聽的事件名
EventEmitter.prototype.eventNames = function () {
    return Object.keys(this._events);
};
// 設(shè)置最大監(jiān)聽數(shù)
EventEmitter.prototype.setMaxListeners = function (n) {
    this._count = n;
};
// 返回監(jiān)聽數(shù)
EventEmitter.prototype.getMaxListeners = function () {
    return this._count ? this._count : this.defaultMaxListeners;
};
接下來是on函數(shù)的實(shí)現(xiàn)
EventEmitter.prototype.on = function (type, cb, flag) {
    // 不是newListener 就應(yīng)該讓newListener執(zhí)行以下
    if (type !== "newListener") {
        this._events["newListener"] && this._events["newListener"].forEach(listener => {
            listener(type);
        });
    }
    if (this._events[type]) {
        // 根據(jù)傳入的flag來決定是向前還是向后添加
        if (flag) {
            this._events[type].unshift(cb);
        } else {
            this._events[type].push(cb);
        }
    } else {
        this._events[type] = [cb];
    }
    // 監(jiān)聽的事件不能超過了設(shè)置的最大監(jiān)聽數(shù)
    if (this._events[type].length === this.getMaxListeners()) {
        console.warn("警告-監(jiān)聽器Number過大");
    }
};

解析:
on函數(shù)是幫定的初始函數(shù),首先判斷是否是首次進(jìn)行偵聽,如果是的話,先進(jìn)行一遍初始化函數(shù)
接下來在——events隊(duì)列里找到指針為type的地方,根據(jù)flag判斷是在隊(duì)列尾還是頭加入callback函數(shù)

接下來是once監(jiān)聽一次的實(shí)現(xiàn)方法
// 監(jiān)聽一次
EventEmitter.prototype.once = function (type, cb, flag) {
    // 先綁定,調(diào)用后刪除
    function wrap() {
        cb(...arguments);
        this.removeListener(type, wrap);
    }
    // 自定義屬性
    wrap.listen = cb;
    this.on(type, wrap, flag);
};

解析:
實(shí)現(xiàn)為在callback上包裝一層remove操作,再當(dāng)做一個(gè)新的callback傳入on函數(shù)
這樣的的話在首次執(zhí)行回調(diào)的時(shí)候就會(huì)執(zhí)行remove操作,達(dá)到執(zhí)行一次就刪除的操作

接下來是remove函數(shù),刪除一個(gè)type的偵聽器
EventEmitter.prototype.removeListener = function (type, cb) {
    if (this._events[type]) {
        this._events[type] = this._events[type].filter(listener => {
            return cb !== listener && cb !== listener.listen;
        });
    }
};

解析:
傳入type和要?jiǎng)h除的callback,對(duì)type標(biāo)記的數(shù)組進(jìn)行 filter操作,假如cb cb === listener則過濾掉

刪除所有
EventEmitter.prototype.removeAllListener = function () {
    this._events = Object.create(null);
};
接下來是發(fā)布函數(shù) emit
EventEmitter.prototype.emit = function (type, ...args) {
    if (this._events[type]) {
        this._events[type].forEach(listener => {
            listener.call(this, ...args);
        });
    }
};

解析:
也比較直觀,如果events里面存在type的監(jiān)聽器隊(duì)列,則隊(duì)列里的每個(gè)回調(diào)都執(zhí)行一遍,并且用call函數(shù)綁定this和arg

完整代碼
//EventEmitter.js


function EventEmitter() {
    // 用Object.create(null)代替空對(duì)象{}
    // 好處是無雜質(zhì),不繼承原型鏈的東東
    this._events = Object.create(null);
}
// 默認(rèn)最多的綁定次數(shù)
EventEmitter.defaultMaxListeners = 10;
// 同on方法
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
// 返回監(jiān)聽的事件名
EventEmitter.prototype.eventNames = function () {
    return Object.keys(this._events);
};
// 設(shè)置最大監(jiān)聽數(shù)
EventEmitter.prototype.setMaxListeners = function (n) {
    this._count = n;
};
// 返回監(jiān)聽數(shù)
EventEmitter.prototype.getMaxListeners = function () {
    return this._count ? this._count : this.defaultMaxListeners;
};
// 監(jiān)聽
EventEmitter.prototype.on = function (type, cb, flag) {
    // 默認(rèn)值,如果沒有_events的話,就給它創(chuàng)建一個(gè)
    if (!this._events) {
        this._events = Object.create(null);
    }
    // 不是newListener 就應(yīng)該讓newListener執(zhí)行以下
    if (type !== "newListener") {
        this._events["newListener"] && this._events["newListener"].forEach(listener => {
            listener(type);
        });
    }
    if (this._events[type]) {
        // 根據(jù)傳入的flag來決定是向前還是向后添加
        if (flag) {
            this._events[type].unshift(cb);
        } else {
            this._events[type].push(cb);
        }
    } else {
        this._events[type] = [cb];
    }
    // 監(jiān)聽的事件不能超過了設(shè)置的最大監(jiān)聽數(shù)
    if (this._events[type].length === this.getMaxListeners()) {
        console.warn("警告-警告-警告");
    }
};
// 向前添加
EventEmitter.prototype.prependListener = function (type, cb) {
    this.on(type, cb, true);
};
EventEmitter.prototype.prependOnceListener = function (type, cb) {
    this.once(type, cb, true);
};
// 監(jiān)聽一次
EventEmitter.prototype.once = function (type, cb, flag) {
    // 先綁定,調(diào)用后刪除
    function wrap() {
        cb(...arguments);
        this.removeListener(type, wrap);
    }
    // 自定義屬性
    wrap.listen = cb;
    this.on(type, wrap, flag);
};
// 刪除監(jiān)聽類型
EventEmitter.prototype.removeListener = function (type, cb) {
    if (this._events[type]) {
        this._events[type] = this._events[type].filter(listener => {
            return cb !== listener && cb !== listener.listen;
        });
    }
};
EventEmitter.prototype.removeAllListener = function () {
    this._events = Object.create(null);
};
// 返回所有的監(jiān)聽類型
EventEmitter.prototype.listeners = function (type) {
    return this._events[type];
};
// 發(fā)布
EventEmitter.prototype.emit = function (type, ...args) {
    if (this._events[type]) {
        this._events[type].forEach(listener => {
            listener.call(this, ...args);
        });
    }
};

module.exports = EventEmitter;

我的博客即將同步至騰訊云+社區(qū),邀請(qǐng)大家一同入駐:https://cloud.tencent.com/dev...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103329.html

相關(guān)文章

  • Node 之 Event 模塊

    摘要:為什么把叫做集合而不能稱為嚴(yán)格意義上的對(duì)象,來看這個(gè)集合的構(gòu)造函數(shù)可以見得,是與處于同一層級(jí)的而非是繼承自,所以說由實(shí)例出來的對(duì)象更加的純凈,并沒有諸如等方法,更像是一個(gè)集合。 寫在前面 事件的編程方式具有輕量級(jí)、松耦合、只關(guān)注事務(wù)點(diǎn)等優(yōu)勢(shì),在瀏覽器端,有著自己的一套DOM事件機(jī)制,其中含包括這諸如事件冒泡,事件捕獲等;然而Node的事件機(jī)制沒有事件冒泡等,其原理就是設(shè)計(jì)模式中的觀察者...

    mrli2016 評(píng)論0 收藏0
  • 從觀察者模式到手寫EventEmitter源碼

    摘要:觀察者模式觀察者模式廣泛的應(yīng)用于語言中,瀏覽器事件如鼠標(biāo)單擊,鍵盤事件都是該模式的例子。可以看到,這就是觀察者模式的訂閱方法實(shí)現(xiàn)。小結(jié)通過創(chuàng)建可觀察的對(duì)象,當(dāng)發(fā)生一個(gè)感興趣的事件時(shí)可將該事件通告給所有觀察者,從而形成松散的耦合。 觀察者模式 觀察者模式(observer)廣泛的應(yīng)用于javascript語言中,瀏覽器事件(如鼠標(biāo)單擊click,鍵盤事件keyDown)都是該模式的例子。...

    cocopeak 評(píng)論0 收藏0
  • 解析nodeJS模塊源碼 親手打造基于ES6的觀察者系統(tǒng)

    摘要:為指定事件注冊(cè)一個(gè)單次監(jiān)聽器,即監(jiān)聽器最多只會(huì)觸發(fā)一次,觸發(fā)后立刻解除該監(jiān)聽器。移除指定事件的某個(gè)監(jiān)聽器,監(jiān)聽器必須是該事件已經(jīng)注冊(cè)過的監(jiān)聽器。返回指定事件的監(jiān)聽器數(shù)組。如何創(chuàng)建空對(duì)象我們已經(jīng)了解到,是要來儲(chǔ)存監(jiān)聽事件監(jiān)聽器數(shù)組的。 毫無疑問,nodeJS改變了整個(gè)前端開發(fā)生態(tài)。本文通過分析nodeJS當(dāng)中events模塊源碼,由淺入深,動(dòng)手實(shí)現(xiàn)了屬于自己的ES6事件觀察者系統(tǒng)。千萬不...

    csRyan 評(píng)論0 收藏0
  • JavaScript 發(fā)布-訂閱模式

    摘要:發(fā)布訂閱模式訂閱者把自己想訂閱的事件注冊(cè)到調(diào)度中心,當(dāng)發(fā)布者發(fā)布該事件到調(diào)度中心,也就是該事件觸發(fā)時(shí),由調(diào)度中心統(tǒng)一調(diào)度訂閱者注冊(cè)到調(diào)度中心的處理代碼。 發(fā)布-訂閱模式,看似陌生,其實(shí)不然。工作中經(jīng)常會(huì)用到,例如 Node.js EventEmitter 中的 on 和 emit 方法;Vue 中的 $on 和 $emit 方法。他們都使用了發(fā)布-訂閱模式,讓開發(fā)變得更加高效方便。 一...

    13651657101 評(píng)論0 收藏0
  • EventEmitter的實(shí)現(xiàn)

    摘要:實(shí)例方法的話,最核心的就是分別是添加事件,刪除事件,發(fā)布事件。為了防止進(jìn)程崩潰,可以在對(duì)象的事件上注冊(cè)監(jiān)聽器,或使用模塊。注意,模塊已被廢棄。作為最佳實(shí)踐,應(yīng)該始終為事件注冊(cè)監(jiān)聽器。 前言 事件在js中非常的常見,不管是瀏覽器還是node,這種事件發(fā)布/訂閱模式的應(yīng)用都是很常見的。至于發(fā)布/訂閱模式和觀察者模式是否是同一種設(shè)計(jì)模式說法都有,這里不做具體的討論。在之前的項(xiàng)目中也曾自己實(shí)現(xiàn)...

    CoreDump 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<