等待在 process.nextTick() 上触发的多个事件
【Awaiting multiple events emitted on process.nextTick()】
在使用 events.once() 函数来等待同一批 process.nextTick() 操作中触发的多个事件,或在多次事件同步触发时,有一个值得注意的边缘情况。具体来说,由于 process.nextTick() 队列会在 Promise 微任务队列之前被清空,并且由于 EventEmitter 会同步触发所有事件,因此 events.once() 可能会遗漏某些事件。
【There is an edge case worth noting when using the events.once() function
to await multiple events emitted on in the same batch of process.nextTick()
operations, or whenever multiple events are emitted synchronously. Specifically,
because the process.nextTick() queue is drained before the Promise microtask
queue, and because EventEmitter emits all events synchronously, it is possible
for events.once() to miss an event.】
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));要同时捕获这两个事件,需要在等待任意一个事件之前先创建每个 Promise,然后就可以使用 Promise.all()、Promise.race() 或 Promise.allSettled():
【To catch both events, create each of the Promises before awaiting either
of them, then it becomes possible to use Promise.all(), Promise.race(),
or Promise.allSettled():】
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));