What is async-exit-hook?
The async-exit-hook npm package allows you to register asynchronous functions that will be called when the Node.js process is exiting. This is useful for cleanup tasks, such as closing database connections, saving state, or other asynchronous operations that need to be completed before the process exits.
What are async-exit-hook's main functionalities?
Registering an asynchronous exit hook
This feature allows you to register an asynchronous function that will be called when the process is exiting. The function can perform any necessary cleanup tasks and must call the provided callback when done.
const exitHook = require('async-exit-hook');
exitHook(async (callback) => {
console.log('Process is exiting...');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Cleanup done.');
callback();
});
// Simulate process exit
die();
Registering multiple exit hooks
You can register multiple asynchronous exit hooks. Each hook will be called in the order they were registered, allowing for complex cleanup sequences.
const exitHook = require('async-exit-hook');
exitHook(async (callback) => {
console.log('First hook');
await new Promise(resolve => setTimeout(resolve, 500));
callback();
});
exitHook(async (callback) => {
console.log('Second hook');
await new Promise(resolve => setTimeout(resolve, 500));
callback();
});
// Simulate process exit
die();
Handling signals
The package can handle various signals (e.g., SIGINT, SIGTERM) and execute the registered hooks when such signals are received, ensuring proper cleanup before the process exits.
const exitHook = require('async-exit-hook');
exitHook(async (callback) => {
console.log('Received signal, cleaning up...');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Cleanup done.');
callback();
});
// Simulate receiving a signal
process.kill(process.pid, 'SIGINT');
Other packages similar to async-exit-hook
exit-hook
The exit-hook package allows you to register synchronous functions to be called when the process exits. Unlike async-exit-hook, it does not support asynchronous operations, making it less suitable for tasks that require asynchronous cleanup.
node-cleanup
The node-cleanup package provides a way to register cleanup handlers that are called when the process exits. It supports both synchronous and asynchronous cleanup functions, similar to async-exit-hook, but offers additional features like handling uncaught exceptions and unhandled promise rejections.
signal-exit
The signal-exit package allows you to execute a callback when the process exits or receives a termination signal. It supports both synchronous and asynchronous callbacks, similar to async-exit-hook, but focuses more on handling various exit signals and conditions.
async-exit-hook
Run some code when the process exits
The process.on('exit')
event doesn't catch all the ways a process can exit. This module catches:
- process SIGINT, SIGTERM and SIGHUP, SIGBREAK signals
- process beforeExit and exit events
- PM2 clustering process shutdown message (PM2 graceful reload)
Useful for cleaning up. You can also include async handlers, and add custom events to hook and exit on.
Forked and pretty much rewritten from exit-hook.
Install
$ npm install --save async-exit-hook
Usage
Considerations and warning
On process.exit()
and asynchronous code
If you use asynchronous exit hooks, DO NOT use process.exit()
to exit.
The exit
event DOES NOT support asynchronous code.
['beforeExit' is not emitted for conditions causing explicit termination, such as process.exit()]
(https://nodejs.org/api/process.html#process_event_beforeexit)
Windows and process.kill(signal)
On windows process.kill(signal)
immediately kills the process, and does not fire signal events,
and as such, cannot be used to gracefully exit. See Clustering and child processes for a
workaround when killing child processes. I'm planning to support gracefully exiting
with async support on windows soon.
Clustering and child processes
If you use custom clustering / child processes, you can gracefully shutdown your child process
by sending a shutdown message (childProc.send('shutdown')
).
Example
const exitHook = require('async-exit-hook');
exitHook(() => {
console.log('exiting');
});
exitHook(() => {
console.log('exiting 2');
});
exitHook(callback => {
setTimeout(() => {
console.log('exiting 3');
callback();
}, 1000);
});
exitHook.uncaughtExceptionHandler(err => {
console.error(err);
});
exitHook.unhandledRejectionHandler(err => {
console.error(err);
});
exitHook.uncaughtExceptionHandler((err, callback) => {
sendErrorToCloudOrWhatever(err)
.then(() => {
console.log('Sent err to cloud');
});
.catch(sendError => {
console.error('Error sending to cloud: ', err.stack));
})
.then(() => callback);
});
});
exitHook.hookEvent('SIGBREAK', 21);
exitHook.hookEvent('message', 0, msg => msg !== 'customShutdownMessage');
throw new Error('awesome');
License
MIT © Tapani Moilanen
MIT © Sindre Sorhus