假設我們有一個發射器物件實作一些邏輯,另一個不同型別的物件根據發射器物件觸發的事件實作一些其他邏輯。我想,我們可以簡單地通過在發射器中使用 function[pointer] 來解決這個問題,并通過使用添加監聽器物件的監聽器函式的函式來更改它們的目標,如下面的代碼。即使我們可以洗掉它。就像 DOM 事件一樣,我可以說。
你能為這個以前來自其他職業的新手推薦一個更好的方法嗎?提前致謝。
class Emitter {
constructor() {
this.event1 = this.empty;
this.event2 = this.empty;
}
empty(){}
someEmmitterLogic(input) {
// arbitrary logic here before event1 occurs
this.event1({message:"produced at event1", b:1});
// maybe event2 can also occur here
this.event2({message:"produced at event2", d:2});
}
addEvent(event, listener) {
switch (event) {
case "event1":
this.event1 = listener;
break;
case "event2":
this.event2 = listener;
break;
default:
console.log("Sorry, we don't emit this event.");
}
}
removeEvent(event) {
switch (event) {
case "event1":
this.event1 = this.empty;
break;
case "event2":
this.event2 = this.empty;
break;
default:
console.log("Sorry, cannot remove an event we are not emitting.");
}
}
}
class Listener{
constructor(){
// Simple listeners outputting the event object to the console
this.listener1 = (e) => console.log(e.message);
this.listener2 = (e) => console.log(e.message);
}
}
///////////////////////////////////////////////////////////////////////////
const emitter = new Emitter();
const listener = new Listener();
console.log("STATUS: not listening emitter");
emitter.someEmmitterLogic();
// Add listeners
emitter.addEvent("event1", listener.listener1);
emitter.addEvent("event2", listener.listener2);
console.log("STATUS: started listening emitter");
emitter.someEmmitterLogic();
console.log("say we don't need event1 anymore, let's remove it");
emitter.removeEvent("event1");
console.log("STATUS: listening event2 only");
emitter.someEmmitterLogic();
.as-console-wrapper {
max-height: 100% !important;
}
小提琴上面的代碼
uj5u.com熱心網友回復:
活動
以這種方式使用事件是提供這種通信的一種行之有效的方式。如果您尋找Node.js等事件發射器的現有實作或搜索“發布/訂閱”,您會發現很多可以借鑒的現有技術。
一些注意事項:
- 通常,您希望擁有一組事件處理程式,而不是只允許一個。
- 通常,發射器會將對事件處理程式的呼叫包裝在
try/catch塊中,以便引發錯誤的處理程式不會阻止發射器代碼繼續執行其作業(通常只是通知事件的偵聽器)。 - 一些系統(包括 DOM)為所有監聽器提供相同的事件物件,允許它們之間有一點串擾。不受控制的串擾可能是個壞主意,但某種形式的受控串擾可能有用。
- 類似地,一些系統(包括 DOM)為事件偵聽器提供了一種取消事件的方法,防止它到達其他偵聽器。
協程
當需要觀察序列(在非常廣泛的意義上)時,沿著這些思路進行通信的另一種方法是使用協程。在 JavaScript 中,可以使用生成器來實作協程,生成器最容易通過生成器函式創建。生成器是一個物件,它產生和使用值以回應對其next方法的呼叫。
這是一個非常簡單的生成器,它只產生(不消耗)值:
// Generator function (note the `*` after `function`) returns
// a generator. This generator provides a series of values in
// a given range (inclusive).
function* range(from = 1, to = 10) {
console.log("Generator: Starting");
for (let value = from; value <= to; value) {
console.log(`Generator: Ready with value ${value}`);
yield value;
}
}
// A popular way to consume generators (and iterables in general) is
// the `for-of` loop. When the generator/iterable is infinite
// as in our case, you need to be sure to break out of it at some point.
for (const value of range(1, 5)) {
console.log(`for-of: Received ${value}`);
}
console.log(`Done`);
.as-console-wrapper {
max-height: 100% !important;
}
請注意生成器的邏輯(在這種情況下是非常簡單的邏輯,一個for回圈)和它的使用者(同樣非常簡單,for-of回圈)是如何混合在一起的。
生成器是生成類似的可迭代物件的好方法,但它們也可以使用推送給它們的值。要將值推送到生成器,您next直接呼叫而不是隱式呼叫。這是另一個簡單的生成器示例,但它既產生值又消耗值——這是一個簡單的 1-100 數字猜謎游戲,生成器負責選擇數字并告訴你猜的好壞:
function* hiddenNumber(from = 1, to = 100) {
console.log("Generator: Starting");
const size = (to - from 1);
const num = Math.floor(Math.random() * size) from;
// console.log("cheat: " num);
let guess = yield `Pick a number between ${from} and ${to} (inclusive)`;
while (guess !== num) {
if (guess < num) {
if (Math.abs(num - guess) >= size / 2) {
guess = yield "REALLY low";
} else {
guess = yield "too low";
}
} else if (guess > num) {
if (Math.abs(num - guess) >= size / 2) {
guess = yield "REALLY high";
} else {
guess = yield "too high";
}
}
}
return "you got it!";
}
const prompt = document.getElementById("prompt");
const input = document.getElementById("input");
const button = document.getElementById("button");
const doGuess = () => {
const num = input.valueAsNumber;
const result = game.next(num);
const answer = result.value;
prompt.textContent = answer;
if (result.done) {
button.disabled = true;
} else {
input.focus();
input.select();
}
};
const game = hiddenNumber();
prompt.textContent = game.next().value;
button.addEventListener("click", doGuess);
input.addEventListener("keypress", event => {
if (event.key === "Enter") {
doGuess();
}
});
input.select();
<p id="prompt"></p>
<input id="input" type="number" value="0" step="1">
<input id="button" type="button" value="Guess">
您可以看到使用它的代碼 ( doGuess) 與生成器的邏輯的互動。
協程確實很有用,但(恕我直言)可能不如事件發射器通用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/428608.html
標籤:javascript 哎呀 事件处理
