在等待多个事件时的注意事项
🌐 Caveats when awaiting multiple events
在使用 events.once() 方法等待多个事件时,了解执行顺序是很重要的。
🌐 It is important to be aware of execution order when using the events.once()
method to await multiple events.
传统的事件监听器在事件被触发时会同步调用。这保证了在所有监听器执行完毕之前,执行不会超出已触发的事件。
🌐 Conventional event listeners are called synchronously when the event is emitted. This guarantees that execution will not proceed beyond the emitted event until all listeners have finished executing.
当等待由 events.once() 返回的 Promise 时情况并非如此。Promise 任务要等到当前执行堆栈运行完成后才会处理,这意味着在相关的 await 语句继续异步执行之前,可能会发出多个事件。
🌐 The same is not true when awaiting Promises returned by events.once().
Promise tasks are not handled until after the current execution stack runs to
completion, which means that multiple events could be emitted before
asynchronous execution continues from the relevant await statement.
因此,如果使用一系列 await events.once() 语句来监听多个事件,可能会“遗漏”某些事件,因为在事件循环的同一阶段可能会有多个事件被触发。(使用 process.nextTick() 触发事件时也是同样的道理,因为 process.nextTick() 排队的任务会在 Promise 任务之前执行。)
🌐 As a result, events can be "missed" if a series of await events.once()
statements is used to listen to multiple events, since there might be times
where more than one event is emitted during the same phase of the event loop.
(The same is true when using process.nextTick() to emit events, because the
tasks queued by process.nextTick() are executed before Promise tasks.)
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function listen() {
await once(myEE, 'foo');
console.log('foo');
// This Promise will never resolve, because the 'bar' event will
// have already been emitted before the next line is executed.
await once(myEE, 'bar');
console.log('bar');
}
process.nextTick(() => {
myEE.emit('foo');
myEE.emit('bar');
});
listen().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function listen() {
await once(myEE, 'foo');
console.log('foo');
// This Promise will never resolve, because the 'bar' event will
// have already been emitted before the next line is executed.
await once(myEE, 'bar');
console.log('bar');
}
process.nextTick(() => {
myEE.emit('foo');
myEE.emit('bar');
});
listen().then(() => console.log('done'));要捕获多个事件,请在等待其中任何一个之前先创建所有的 Promise。这通常可以通过使用 Promise.all()、Promise.race() 或 Promise.allSettled() 来更容易实现:
🌐 To catch multiple events, create all of the Promises before awaiting any of
them. This is usually made easier by using Promise.all(), Promise.race(),
or Promise.allSettled():
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function listen() {
await Promise.all([
once(myEE, 'foo'),
once(myEE, 'bar'),
]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('foo');
myEE.emit('bar');
});
listen().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function listen() {
await Promise.all([
once(myEE, 'bar'),
once(myEE, 'foo'),
]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('foo');
myEE.emit('bar');
});
listen().then(() => console.log('done'));