首頁  >  文章  >  web前端  >  JavaScript EventEmitter底層邏輯剖析

JavaScript EventEmitter底層邏輯剖析

php中世界最好的语言
php中世界最好的语言原創
2018-05-26 10:43:121238瀏覽

這次帶給大家JavaScript EventEmitter底層邏輯剖析,JavaScript EventEmitter底層邏輯剖析的注意事項有哪些,下面就是實戰案例,一起來看一下。

什麼是 Event Emitter?

Event emitter 聽起來只是觸發一個事件,這個事件任何東西都能監聽。

想像這樣的場景,在你的非同步程式碼中,去「呼叫」一些事件的發生,以及讓你其他部分都要聽到你的「呼叫」並且註冊他們的想法。

為了不同的目的,對於 Event Emitter 模式有大量不同的實現,但是基本的想法是為了給一個框架提供事件的管理以及能夠去訂閱他們。

在這裡,我們的目標創造出屬於我們自己的 Event Emitter 去理解背後的秘密。所以,讓我們來看看下面的程式碼是怎麼運作的。

let input = document.querySelector("input[type="text"]");
let button = document.querySelector("button");
let h1 = document.querySelector("h1");
button.addEventListener("click", () => {
  emitter.emit("event:name-changed", { name: input.value });
});
let emitter = new EventEmitter();
emitter.subscribe("event:name-changed", data => {
  h1.innerHTML = `Your name is: ${data.name}`;
});

讓我們開始。

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

我們先建立一個 EventEmiiter 類別以及初始化 events 空物件屬性。這個 events 屬性的目的是為了儲存我們的事件集合,這個 events 物件使用事件名稱當做 key,用訂閱者集合當 value。 (可以把每個訂閱者看成是一個函數)。

訂閱函數

subscribe(eventName, fn) {
  if (!this.events[eventName]) {
    this.events[eventName] = [];
  }
  this.events[eventName].push(fn);
}

這個訂閱函數取得事件名稱,在我們之前的範例中,它是"event:name-changed" 以及傳入一個回調,當有人呼叫emit(或尖叫)事件的時候呼叫回調。

JavaScript 函數的優點之一是函數是第一個對象,所以我們能像之前我們的訂閱方法一樣,透過函數作為另一個函數的參數

如果未註冊這個事件,我們需要在第一次為它設定一個初始值,事件名稱作為key 以及初始化一個空數組賦值給它,然後我們將函數放入這個數組,以便我們想透過emit 去呼叫這個事件。

呼叫函數

emit(eventName, data) {
  const event = this.events[eventName];
  if (event) {
    event.forEach(fn => {
      fn.call(null, data);
    });
  }
}

這個呼叫函數接受事件名,這個事件名是我們想要「呼叫」的名稱,以及我們想要傳遞給這個事件的資料。如果在我們的 events 中存在這個事件,我們將帶上資料循環呼叫所有訂閱的方法。

使用上面的程式碼能做我們所說的全部的事情。但我們仍然有一個問題。當我們不再需要它們的時候,我們需要一種方法來取消註冊這些訂閱,因為如果你不這樣做,將造成記憶體洩漏。

讓我們來解決這個問題,透過在訂閱函數中傳回一個取消註冊的方法。

subscribe(eventName, fn) {
  if (!this.events[eventName]) {
    this.events[eventName] = [];
  }
  this.events[eventName].push(fn);
  return () => {
    this.events[eventName] = this.events[eventName].filter(eventFn => fn !== eventFn);
  }
}

因為 JavaScript 函數是第一對象,你能在一個函數中傳回一個函數。因此現在我們能呼叫這個取消註冊函數,如下:

let unsubscribe = emitter.subscribe("event:name-changed", data => console.log(data));
unsubscribe();

當我們呼叫取消註冊函數的時候,我們刪除的功能依賴於訂閱函數集合的篩選方法(Array filter)。

和記憶體洩漏說再見!

以上是JavaScript EventEmitter底層邏輯剖析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn