Search code examples
node.jsconsoleeventemitter

node.js console async app "best practice"


Periodically, I have to write node.js console applications that are meant to be run directly from the shell. They do not accept input, they'll call the file system, do database calls and other async type activities. Examples abound on how to set up node.js applications that are hosting a server and such, but for something that calls an async process, waits for it, and then exits after setting the exit code. I'm having a hard time finding what I would consider graceful examples.

Here is a snippet of how I'm addressing this for now. Any node.js gurus have any cleaner ways to go about this, or is this mostly "ok"?

const emitter = new EventEmitter();
emitter.on('exit', (err) => {
    if(err) {
        console.error(err instanceof Error ? err.message : err);
        process.exit(-1);
    } else {
        process.exit(0);
    }
});

setImmediate(async () => {
    try {
        await doSomeAsyncThing();
        emitter.emit('exit', null);
    } catch(e) {
        emitter.emit('exit', e);
    }
});

Solution

  • This is the purpose of unhandledRejection event. It outputs UnhandledPromiseRejectionWarning and is expected to cause an exception in future Node versions by default. Since this is the intention here, it can be:

    process.on('unhandledRejection', (err) => {
        console.error(err instanceof Error ? err.message : err);
        process.exit(-1);
    });
    
    (async () => {
        try {
            await doSomeAsyncThing();
            process.exit(0);
        } catch(e) {
            throw e;
        }
    })();