Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform an async operation on exit

I've been trying to perform an asynchronous operation before my process is terminated.

Saying 'terminated' I mean every possibility of termination:

  • ctrl+c
  • Uncaught exception
  • Crashes
  • End of code
  • Anything..

To my knowledge the exit event does that but for synchronous operations.

Reading the Nodejs docs i found the beforeExit event is for the async operations BUT :

The 'beforeExit' event is not emitted for conditions causing explicit termination, such as calling process.exit() or uncaught exceptions.

The 'beforeExit' should not be used as an alternative to the 'exit' event unless the intention is to schedule additional work.

Any suggestions?

like image 727
Kesem David Avatar asked Nov 13 '16 13:11

Kesem David


People also ask

How do you wait for an async function to finish?

Wait for function to finish using async/await keywords As you already know from the Promise explanation above, you need to chain the call to the function that returns a Promise using then/catch functions. The await keyword allows you to wait until the Promise object is resolved or rejected: await first(); second();

Do async functions run automatically?

In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

Does async function return immediately?

Async functions don't return immediately, they run the body of the code until the hit an await and return a promise. In your example, the entire function will run before it returns.

Do you need async If you return a Promise?

If you either catch your own synchronous exceptions or are sure there are no synchronous exceptions and you are controlling all code paths to return a promise, then async is not necessary.


2 Answers

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.
like image 58
Ben Avatar answered Sep 22 '22 06:09

Ben


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 }); 
like image 22
Sceat Avatar answered Sep 24 '22 06:09

Sceat