站長(zhǎng)資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Node.js學(xué)習(xí)之聊聊Events模塊

        本篇文章帶大家了解一下Node.js中的Events模塊,介紹一下 Events 中的發(fā)布訂閱模式,希望對(duì)大家有所幫助!

        Node.js學(xué)習(xí)之聊聊Events模塊

        Events模塊

        參考官網(wǎng):events 事件觸發(fā)器 | Node.js

        http://nodejs.cn/api/events.html

        Events 模塊是Node最重要的模塊,它提供了一個(gè)屬性 EventEmitterEventEmitter 的核心是事件發(fā)射與事件監(jiān)聽(tīng)器。

        Node中大部分的模塊,都繼承自 Events 模塊。

        • Events 模塊是Node對(duì) 發(fā)布訂閱模式publish/subscribe)的實(shí)現(xiàn)。一個(gè)對(duì)象通過(guò)這個(gè)模塊,向另一個(gè)對(duì)象傳遞消息。
        • 該模塊通過(guò) EventEmitter 屬性,提供了一個(gè)構(gòu)造函數(shù)。該構(gòu)造函數(shù)的實(shí)例具有 on 方法,可以用來(lái)監(jiān)聽(tīng)指定事件,并觸發(fā)回調(diào)函數(shù)。
        • 任意對(duì)象都可以發(fā)布指定事件,被 EventEmitter 實(shí)例的on方法監(jiān)聽(tīng)到。

        發(fā)布訂閱模式

        關(guān)于 發(fā)布訂閱模式 ,可以參考我之前的博客文章。

        關(guān)于 Events 中的發(fā)布訂閱模式,我們要先清楚它的幾個(gè)常用方法。

        • 訂閱方法on 方法用來(lái)訂閱事件,訂閱是將方法對(duì)應(yīng)成一種一對(duì)多的關(guān)系。
        • 發(fā)布方法emit 用來(lái)執(zhí)行訂閱的事件。
        • 取消訂閱off 方法可以移除對(duì)應(yīng)的事件監(jiān)聽(tīng)。
        • 訂閱一次once 綁定事件當(dāng)執(zhí)行后自動(dòng)刪除訂閱的事件。

        on 和 emit

        on 方法的第一個(gè)參數(shù)用來(lái)設(shè)定類(lèi)名,第二個(gè)參數(shù)也是一個(gè)函數(shù),里面可以接收發(fā)布時(shí)傳入的參數(shù)。

        emit 方法第一個(gè)參數(shù)是類(lèi)名,之后的參數(shù)都是傳入 on 方法函數(shù)中的參數(shù)。

        onemit 具體應(yīng)用可以參考下面這個(gè)簡(jiǎn)單的Demo。

        const EventEmitter = require('events'); // 自定義一個(gè) 構(gòu)造函數(shù) function Cat() {} // 原型繼承 需要通過(guò)實(shí)例來(lái)調(diào)用繼承方法 Object.setPrototypeOf(Cat.prototype, EventEmitter.prototype); let cat = new Cat(); const sleep = (a, b) => {     console.log(a, '睡'); }; const eat = (a, b) => {     console.log(b, '吃'); }; cat.on('貓咪', sleep) cat.on('貓咪', eat) setTimeout(() => {   	// 小胡子 吃   	// 小胖仙 睡     cat.emit('貓咪', '小胖仙', '小胡子') }, 1000);

        現(xiàn)在我們可以實(shí)現(xiàn)一套 onemit 方法。

        function EventEmitter() {     this._event = {} } // on 方法 EventEmitter.prototype.on = function (eventName, callBack) {     if (!this._event) {         this._event = {}     }     if (this._event[eventName]) {         this._event[eventName].push(callBack) // 相當(dāng)于 {eventName:[fn1,fn2]}     } else {         this._event[eventName] = [callBack]; // 相當(dāng)于 {eventName:[fn1]}     }  } // emit 方法 EventEmitter.prototype.emit = function (eventName, ...args) {     this._event[eventName].forEach(fn => {         fn(...args)     }); }

        off

        off 方法的第一個(gè)參數(shù)用來(lái)設(shè)定類(lèi)名,第二個(gè)參數(shù)傳入需要被移除的函數(shù)回調(diào)。

        // ... setTimeout(() => {   	// 小胡子 吃   	// 小胖仙 睡     cat.emit('貓咪', '小胖仙', '小胡子')   	cat.off('貓咪', sleep);   	// 小胡子 吃     cat.emit('貓咪', '小胖仙', '小胡子') }, 1000);

        這樣我們可以大概判斷出來(lái),移除掉和我們傳入函數(shù)相同的函數(shù),我們很快想到 filter 方法。

        // off 方法 EventEmitter.prototype.off = function (eventName, callBack) {     if (this._event && this._event[eventName]) {         this._event[eventName] = this._event[eventName].filter(           fn => fn !== callBack && fn.c !== callBack // fn.c參考下面的once方法實(shí)現(xiàn)         )     } }

        once

        once 方法的第一個(gè)參數(shù)用來(lái)設(shè)定類(lèi)名,第二個(gè)參數(shù)傳入只需要執(zhí)行一次的函數(shù)回調(diào)。

        // ... const demolition =() => {     console.log('拆家'); } cat.once('貓咪', demolition) setTimeout(() => {   	// ...... 拆家     cat.emit('貓咪', '小胖仙', '小胡子') }, 1000);

        這樣我們可以根據(jù)之前實(shí)現(xiàn)的 onoff 來(lái)實(shí)現(xiàn)此方法。

        // once 方法 EventEmitter.prototype.once = function (eventName, callBack) {     const one = () => {         callBack();         this.off(eventName, one);     }     this.on(eventName, one); }

        看起來(lái)這個(gè)方法好像沒(méi)有什么問(wèn)題,執(zhí)行起來(lái)也全都是正確的。

        但是在一種特殊情況下的時(shí)候,還是出現(xiàn)了錯(cuò)誤。

        那種情況就是如果我們?cè)趫?zhí)行 once 方法之前,就已經(jīng)通過(guò) off 方法將其移除了。

        我們實(shí)現(xiàn)的方法就不能實(shí)現(xiàn)這個(gè)需求了,所以我們還需要對(duì) once 方法進(jìn)行一些修改 off 方法已經(jīng)處理過(guò)了)

        添加一個(gè)自定義屬性,用來(lái)對(duì)函數(shù)進(jìn)行 “緩存” 。

        EventEmitter.prototype.once = function (eventName, callBack) {     const one = () => {         // ...     }     one.c = callBack; // 自定義一個(gè)屬性     // ... }

        這樣我們就實(shí)現(xiàn)了 once 方法。

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
        主站蜘蛛池模板: 人妻少妇偷人精品无码| 精品国产福利在线观看| 正在播放国产精品每日更新 | 久久精品国产亚洲AV无码娇色| 国产精品99久久久久久宅男| 国产成人精品2021| 一本一本久久a久久综合精品蜜桃| 国产精品极品| 日韩精品免费视频| 91精品视频网站| 久久国产亚洲精品无码| 中文字幕精品一区| 青草青草久热精品视频在线观看| Xx性欧美肥妇精品久久久久久| 3D动漫精品一区二区三区| 久久综合久久自在自线精品自| 欧美人与性动交α欧美精品 | 国产福利精品一区二区| 无码国产精品一区二区免费vr | 成人国产精品高清在线观看| 无码人妻精品一区二区三区在线| 日韩蜜芽精品视频在线观看| 国产偷窥熟女高潮精品视频| 国产精品va久久久久久久| 亚洲精品天天影视综合网| 精品精品国产高清a毛片牛牛| 国语自产精品视频在线区| 精品无码AV一区二区三区不卡| 青青草原精品国产亚洲av| 四虎成人精品无码| 日韩精品乱码AV一区二区| 宅男在线国产精品无码| 亚洲人成精品久久久久| 亚洲精品欧美精品日韩精品| 亚洲精品乱码久久久久久蜜桃| 一区二区国产精品| 亚洲日韩精品无码专区网址| 欧洲精品色在线观看| 老司机亚洲精品影院| 国产精品视频一区二区三区无码| 国产精品视频白浆免费视频|