Can an event listener be an `async` function? If so, explain how errors should be handled within it to prevent unhandled promise rejections.
Node.js interview question for Advanced practice.
Answer
Yes, an event listener can absolutely be an async function. The EventEmitter will await the promise returned by the listener if it was registered with emitter.on in a special way using an async iterator, but in the common case, it simply invokes the function and does not wait for the promise to resolve. This creates a critical error handling challenge: if the promise returned by the async listener rejects, and there is no .catch() handler attached to it, it will cause an UnhandledPromiseRejectionWarning and may terminate the Node.js process in future versions. Error Handling: Errors must be handled inside the async listener function itself. The best way is with a try...catch block. javascript const EventEmitter = require('events'); const emitter = new EventEmitter(); emitter.on('error', (err) = { console.error('Caught an error centrally:', err.message); }); // CORRECT way to handle errors in an async listener emitter.on('doWork', async (task) = { try { console.log(Starting work on: ${task}); const result = await someAsyncOperationThatMightFail(task); console.log(Finished work with result: ${result}); } catch (err) { // Handle the error, e.g., by emitting a central 'error' event emitter.emit('error', err); } }); async function someAsyncOperationThatMightFail(task) { if (task === 'bad') { throw new Error('This task failed!'); } return 'Success'; } emitter.emit('doWork', 'good'); emitter.emit('doWork', 'bad'); // The error will be caught and handled. Simply letting the async function throw is not enough, as the standard EventEmitter will not catch the promise rejection.
Explanation
Since Node.js v12, EventEmitter has experimental support for AbortSignal to cancel async listeners, providing more robust control over asynchronous event handling.