Jeff的隨手筆記

學習當一個前端工程師

0%

用LeetCode寫日記-Day28

加今天還剩下3篇,加油!

Day28: Event Emitter

問題描述:

Design an EventEmitter class. This interface is similar (but with some differences) to the one found in Node.js or the Event Target interface of the DOM. The EventEmitter should allow for subscribing to events and emitting them.

Your EventEmitter class should have the following two methods:

  • subscribe - This method takes in two arguments: the name of an event as a string and a callback function. This callback function will later be called when the event is emitted.An event should be able to have multiple listeners for the same event. When emitting an event with multiple callbacks, each should be called in the order in which they were subscribed. An array of results should be returned. You can assume no callbacks passed to subscribe are referentially identical.The subscribe method should also return an object with an unsubscribe method that enables the user to unsubscribe. When it is called, the callback should be removed from the list of subscriptions and undefined should be returned.
  • emit - This method takes in two arguments: the name of an event as a string and an optional array of arguments that will be passed to the callback(s). If there are no callbacks subscribed to the given event, return an empty array. Otherwise, return an array of the results of all callback calls in the order they were subscribed.

問題難度:Medium

問題限制:

  • 1 <= actions.length <= 10
  • values.length === actions.length
  • All test cases are valid, e.g. you don’t need to handle scenarios when unsubscribing from a non-existing subscription.
  • There are only 4 different actions: EventEmitteremitsubscribe, and unsubscribe.
  • The EventEmitter action doesn’t take any arguments.
  • The emit action takes between either 1 or 2 arguments. The first argument is the name of the event we want to emit, and the 2nd argument is passed to the callback functions.
  • The subscribe action takes 2 arguments, where the first one is the event name and the second is the callback function.
  • The unsubscribe action takes one argument, which is the 0-indexed order of the subscription made before.

我的學習過程:

今天的題目…我完全不會。只好看別人的code來學習:

這個問題是要求你實現一個簡化版的事件發布-訂閱(Publish-Subscribe)模式,即實作一個 EventEmitter 類別。這個模式常見於事件驅動的編程中,例如在 Node.js 或網頁開發中的 DOM 事件。

以下是 EventEmitter 類別的主要方法:

  1. subscribe(event, cb): 訂閱事件。這個方法接受兩個參數,一個是事件名稱(字串),另一個是回調函數(callback)。訂閱後,當事件被觸發時,這個回調函數將被呼叫。如果同一事件有多個訂閱者(多個回調函數),它們應該按照訂閱的順序被呼叫。方法會返回一個物件,該物件有一個 unsubscribe 方法,呼叫此方法可以取消訂閱。
  2. emit(event, args = []): 觸發事件。這個方法接受兩個參數,一個是事件名稱(字串),另一個是一個可選的參數陣列,這個陣列的內容將被傳遞給訂閱的回調函數。如果該事件沒有被訂閱,則返回一個空陣列;否則,返回一個包含所有回調函數執行結果的陣列。

作者的教學:

使用的概念:

Map:使用 Map 數據結構來存儲事件作為鍵,並將回調的數組作為值。它允許高效地檢索和操作事件監聽器。

Subscriptions:當訂閱事件時,回調函數被添加到該事件的聽眾數組中。subscribe 方法返回一個帶有取消訂閱方法的對象,該方法允許從事件的聽眾中刪除回調。

Callbacks and Arguments:與事件關聯的回調在發出事件時可以接收可選參數。emit 方法使用提供的參數依次調用每個回調,並收集結果。

Approach:

在 EventEmitter 構造函數中,初始化了一個名為 events 的內部 Map,用於將事件名稱存儲為鍵,回調的數組存儲為值。

subscribe 方法檢查事件是否已經存在於 events map 中。如果不存在,則為該事件創建一個空數組。

提供的回調函數(cb)被添加到指定事件的回調數組中。

subscribe 方法返回帶有取消訂閱方法的對象。這允許用戶通過找到其索引並從數組中切割它來從訂閱列表中刪除回調。

emit 方法檢查 events map 中是否存在事件。如果不存在,則返回一個空數組,因為沒有訂閱該事件的回調。

如果事件存在,則檢索該事件的回調數組。然後,該方法遍歷每個回調並使用提供的參數(args)調用它們。

每個回調調用的結果存儲在一個數組(results)中,該數組在方法末尾被返回。

通過使用 Map 數據結構,代碼高效地組織了事件和相應的回調。該類別通過在訂閱時返回一個帶有取消訂閱方法的對象,提供了清晰和直觀的界面。該實現確保事件可以有多個聽眾,並確保已訂閱的事件以它們被訂閱的順序觸發相應的回調。

解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class EventEmitter {
constructor() {
this.events = new Map();
}

subscribe(event, cb) {
if (!this.events.has(event)) {
this.events.set(event, []);
}

const listeners = this.events.get(event);
listeners.push(cb);

return {
unsubscribe: () => {
const index = listeners.indexOf(cb);
if (index !== -1) {
listeners.splice(index, 1);
}
}
};
}

emit(event, args = []) {
if (!this.events.has(event)) {
return [];
}

const listeners = this.events.get(event);
const results = [];

for (const listener of listeners) {
results.push(listener(...args));
}

return results;
}
}

結論:

這是這28天來第一次就算看了解答還搞不清楚的東西,暫時先跳過。等之後有時間再回來研究一下這個東西