How to perform an async operation on exit How to perform an async operation on exit typescript typescript

How to perform an async operation on exit


You can trap the signals and perform your async task before exiting. Something like this will call terminator() function before exiting (even javascript error in the code):

process.on('exit', function () {    // Do some cleanup such as close db    if (db) {        db.close();    }});// catching signals and do something before exit['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',    'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM'].forEach(function (sig) {    process.on(sig, function () {        terminator(sig);        console.log('signal: ' + sig);    });});function terminator(sig) {    if (typeof sig === "string") {        // call your async task here and then call process.exit() after async task is done        myAsyncTaskBeforeExit(function() {            console.log('Received %s - terminating server app ...', sig);            process.exit(1);        });    }    console.log('Node server stopped.');}

Add detail requested in comment:

  • Signals explained from node's documentation, this link refers to standard POSIX signal names
  • The signals should be string. However, I've seen others have done the check so there might be some other unexpected signals that I don't know about. Just want to make sure before calling process.exit(). I figure it doesn't take much time to do the check anyway.
  • for db.close(), I guess it depends on the driver you are using. Whether it's sync of async. Even if it's async, and you don't need to do anything after db closed, then it should be fine because async db.close() just emits close event and the event loop would continue to process it whether your server exited or not.


Using beforeExit hook

The 'beforeExit' event is emitted when Node.js empties its event loop and has no additional work to schedule. Normally, the Node.js process will exit when there is no work scheduled, but a listener registered on the 'beforeExit' event can make asynchronous calls, and thereby cause the Node.js process to continue.

process.on('beforeExit', async () => {    await something()    process.exit(0) // if you don't close yourself this will run forever});


Here's my take on this. A bit long to post as a code snippet in here, so sharing a Github gist.

https://gist.github.com/nfantone/1eaa803772025df69d07f4dbf5df7e58

It's pretty straightforward. You use it like so:

'use strict';const beforeShutdown = require('./before-shutdown');// Register shutdown callbacks: they will be executed in the order they were providedbeforeShutdown(() => db.close());beforeShutdown(() => server.close());beforeShutdown(/* Do any async cleanup */);

The above will listen for a certain set of system signals (SIGINT, a.k.a Ctrl + C, and SIGTERM by default) and call each handler in order before shutting down the whole process.

It also,

  • Supports async callbacks (or returning a Promise).
  • Warns about failing shutdown handlers, but prevents the error/rejection from bubbling up.
  • Forces shutdown if handlers do not return after some time (15 seconds, by default).
  • Callbacks can be registered from any module in your code base.