events.once(emitter, name[, options])
#emitter
<EventEmitter>
name
<string>
options
<Object>
signal
<AbortSignal>
<Promise>
Creates a 创建一个Promise
that is fulfilled when the EventEmitter
emits the given event or that is rejected if the EventEmitter
emits 'error'
while waiting. Promise
,该Promise在EventEmitter
发出给定事件时实现,或者如果EventEmitter
在等待时发出'error'
则被拒绝。The Promise
will resolve with an array of all the arguments emitted to the given event.Promise
将使用向给定事件发出的所有参数的数组进行解析。
This method is intentionally generic and works with the web platform EventTarget interface, which has no special 此方法是故意通用的,并与web平台EventTarget接口一起使用,后者没有特殊的'error'
event semantics and does not listen to the 'error'
event.'error'
事件语义,也不侦听'error'
消息。
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.log('error happened', err);
}
const { once, EventEmitter } = require('node:events');
async function run() {
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.log('error happened', err);
}
}
run();
The special handling of the 只有当'error'
event is only used when events.once()
is used to wait for another event. events.once()
用于等待另一个事件时,才会使用'error'
事件的特殊处理。If 如果events.once()
is used to wait for the 'error'
event itself, then it is treated as any other kind of event without special handling:eventsonce()
用于等待'error'
事件本身,那么它将被视为任何其他类型的事件,而无需特殊处理:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.log('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.log('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
An <AbortSignal>
can be used to cancel waiting for the event:<AbortSignal>
可用于取消等待事件:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
process.nextTick()
process.nextTick()
上发出的多个事件#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. events.once()
函数等待在同一批process.nextTick()
操作中发出的多个事件时,或者当多个事件同时发出时,有一个边缘情况值得注意。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.process.nextTick()
队列在Promise微任务队列之前耗尽,并且EventEmitter
同步发出所有事件,因此events.once()
可能会错过事件。
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'));
To catch both events, create each of the Promises before awaiting either of them, then it becomes possible to use 要捕获这两个事件,请在等待其中一个之前创建每个Promise,然后可以使用Promise.all()
, Promise.race()
, or Promise.allSettled()
:Promise.all()
、Promise.race()
或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'));