JS原生實現(xiàn)EventEmitter事件隊列

EventEmitter 是什么

  • Node.js 的 events 模塊對外提供了一個 EventEmitter 對象,用于對 Node.js 中的事件進行統(tǒng)一管理。
  • Node.js 采用了事件驅(qū)動機制蔬崩, EventEmitter 就是 Node.js 實現(xiàn)事件驅(qū)動的基礎(chǔ)连茧,Node.js 中幾乎所有的模塊都繼承了這個類,以實現(xiàn)異步事件驅(qū)動架構(gòu)产场。
  • Node.js 中幾乎所有的模塊都繼承了這個類唆姐,以實現(xiàn)異步事件驅(qū)動架構(gòu)拗慨。瀏覽器事件(如鼠標(biāo)單擊click廓八,鍵盤事件keyDown)等都是該模式的例子

核心代碼-參考1

使用 events 模塊奉芦,對事件數(shù)組進行管理,
on 添加進事件隊列 addListener
emit 執(zhí)行
off 關(guān)閉 removeListener
once 只執(zhí)行一次剧蹂,結(jié)束后 remove

class EventEmitter {
    constructor(){
        this.events = {}
    }

    on(event, listener){
        let listeners = this.events[event] || []
        listeners.push(listener)
        this.events = listeners

        return this
    }

    emit(event, ...args){
        let listeners = this.events[event]

        listeners.forEach(listener => {
            listener(...args)
        });

        return this
    }

    off(event, listener){
        let listeners = this.events[event]

        this.events[event] = listeners && listeners.filter(fn => fn !== listener) 

        return this
    }

    once(event, listener){
        let fn = function(...args){
            listener(...args)

            this.off(event, listener)
        }

        this.on(event, fn)

        return this
    }
}

優(yōu)化-參考2

添加事件合法性校驗等

function EventEmitter() {
  this.__events = {};
}
EventEmitter.VERSION = "1.0.0";

EventEmitter.prototype.on = function (eventName, listener) {
  // 驗證參數(shù)
  if (!eventName && !listener) {
    return;
  }
  // 回調(diào)的litener是否是函數(shù)
  if (!isValidKistener(listener)) {
    throw new TypeError("listener must be a function");
  }
  const events = this.__evnets;
  const listeners = (events[eventName] = evnets[eventName] || []);
  const listenerIsWrapped = typeof listener === "object";
  // 不重復(fù)添加事件声功,判斷是否有相同
  if (indexOf(listeners.listener) === -1) {
    listeners.push(
      listenerIsWrapped
        ? listener
        : {
            listener: listener,
            once: false,
          }
    );
  }
  return this;
};

//判斷是否是合法的listener
const isValidListener = (listener) => {
  if (typeof listener === "function") {
    return true;
  } else if (listener && typeof listener === "object") {
    return isValidListener(listener.listener);
  } else {
    return false;
  }
};

// 判斷新增自定義事件是否存在
const indexOf = (array, item) => {
  let result = -1;
  item = typeof item === "object" ? item.listener : item;
  for (let i = 0; i < array.length; i++) {
    if (array[i].listener === item) {
      result = i;
      break;
    }
  }
  return result;
};

設(shè)計模式

采用了發(fā)布-訂閱者模式

發(fā)布-訂閱模式其實是一種對象間一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)送改變時宠叼,所有依賴于它的對象都將得到狀態(tài)改變的通知先巴。

  • 訂閱者(Subscriber)把自己想訂閱的事件 注冊(Subscribe)到調(diào)度中心(Event Channel);
  • 當(dāng)發(fā)布者(Publisher)發(fā)布該事件(Publish Event)到調(diào)度中心其爵,也就是該事件觸發(fā)時,由 調(diào)度中心 統(tǒng)一調(diào)度(Fire Event)訂閱者注冊到調(diào)度中心的處理代碼

相關(guān)文章

  1. 一文讓你了解各種原生JS的實現(xiàn)方式
  2. 怎樣輕松實現(xiàn)一個 EventEmitter伸蚯?
  3. 被寫爛系列——實現(xiàn)EventEmitter
  4. 從零帶你手寫一個“發(fā)布-訂閱者模式“ 摩渺,保姆級教學(xué)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市剂邮,隨后出現(xiàn)的幾起案子摇幻,更是在濱河造成了極大的恐慌,老刑警劉巖挥萌,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绰姻,死亡現(xiàn)場離奇詭異,居然都是意外死亡引瀑,警方通過查閱死者的電腦和手機狂芋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憨栽,“玉大人帜矾,你說我怎么就攤上這事⌒既幔” “怎么了黍特?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锯蛀。 經(jīng)常有香客問我灭衷,道長,這世上最難降的妖魔是什么旁涤? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任翔曲,我火速辦了婚禮,結(jié)果婚禮上劈愚,老公的妹妹穿的比我還像新娘瞳遍。我一直安慰自己,他們只是感情好菌羽,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布掠械。 她就那樣靜靜地躺著,像睡著了一般注祖。 火紅的嫁衣襯著肌膚如雪猾蒂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天是晨,我揣著相機與錄音肚菠,去河邊找鬼。 笑死罩缴,一個胖子當(dāng)著我的面吹牛蚊逢,可吹牛的內(nèi)容都是我干的层扶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烙荷,長吁一口氣:“原來是場噩夢啊……” “哼镜会!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起终抽,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤稚叹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拿诸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扒袖,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年亩码,在試婚紗的時候發(fā)現(xiàn)自己被綠了季率。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡描沟,死狀恐怖飒泻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吏廉,我是刑警寧澤泞遗,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站席覆,受9級特大地震影響史辙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜佩伤,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一聊倔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧生巡,春花似錦耙蔑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盐股,卻和暖如春钱豁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遂庄。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工寥院, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涛目。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓秸谢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霹肝。 傳聞我的和親對象是個殘疾皇子估蹄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354