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

Node.js學習之聊聊Events模塊

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

Node.js學習之聊聊Events模塊

Events模塊

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

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

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

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

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

發(fā)布訂閱模式

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

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

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

on 和 emit

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

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

onemit 具體應用可以參考下面這個簡單的Demo。

const EventEmitter = require('events'); // 自定義一個 構(gòu)造函數(shù) function Cat() {} // 原型繼承 需要通過實例來調(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)在我們可以實現(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) // 相當于 {eventName:[fn1,fn2]}     } else {         this._event[eventName] = [callBack]; // 相當于 {eventName:[fn1]}     }  } // emit 方法 EventEmitter.prototype.emit = function (eventName, ...args) {     this._event[eventName].forEach(fn => {         fn(...args)     }); }

off

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

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

這樣我們可以大概判斷出來,移除掉和我們傳入函數(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方法實現(xiàn)         )     } }

once

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

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

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

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

看起來這個方法好像沒有什么問題,執(zhí)行起來也全都是正確的。

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

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

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

添加一個自定義屬性,用來對函數(shù)進行 “緩存” 。

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

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

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
少妇人妻无码精品视频app| 久久久久99精品成人片| 国产乱人伦偷精品视频免| 久久99久久99精品免视看动漫| 亚洲精品卡2卡3卡4卡5卡区| 国产成人精品曰本亚洲79ren| 日韩内射激情视频在线播放免费| 精品丝袜人妻久久久久久| 国产成人精品三级在线| 久久精品国产99国产精品导航 | 亚洲日韩精品无码专区| 日本久久中文字幕精品| 亚洲性色精品一区二区在线| 国产精品一区二区久久精品| 亚洲精品国产成人中文| 人妻AV一区二区三区精品| 久久久久女人精品毛片九一| 久久久久夜夜夜精品国产| 日韩人妻无码精品系列| 国产午夜精品一区二区三区不卡| 国产精品乱码一区二区三区| 日本精品久久久久久久久免费| 日韩高清在线高清免费| 日韩影片在线观看| 日韩在线观看一区二区三区| 亚洲av日韩av无码| 亚洲欭美日韩颜射在线二| 无码日韩人妻AV一区二区三区 | 国产亚洲美女精品久久久| 国产精品国产三级在线高清观看 | 亚洲国产美女精品久久| 亚洲伊人精品综合在合线| 91精品国产高清久久久久久91| 精品一区高潮喷吹在线播放| 亚洲一区精品视频在线| 国产高清国内精品福利| 波多野结衣久久精品| 免费无码精品黄AV电影| 国产精品视_精品国产免费| 国产在热线精品视频| 日韩精品无码人妻一区二区三区|