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.

    1. const { EventEmitter, once } = require('events');
    2. const myEE = new EventEmitter();
    3. async function foo() {
    4. await once(myEE, 'bar');
    5. console.log('bar');
    6. // This Promise will never resolve because the 'foo' event will
    7. // have already been emitted before the Promise is created.
    8. await once(myEE, 'foo');
    9. console.log('foo');
    10. }
    11. process.nextTick(() => {
    12. myEE.emit('bar');
    13. myEE.emit('foo');
    14. });
    15. 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.all(), Promise.race(), or Promise.allSettled():

    1. const { EventEmitter, once } = require('events');
    2. const myEE = new EventEmitter();
    3. async function foo() {
    4. await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
    5. console.log('foo', 'bar');
    6. }
    7. process.nextTick(() => {
    8. myEE.emit('bar');
    9. myEE.emit('foo');
    10. });
    11. foo().then(() => console.log('done'));