UNPKG

3.87 kBMarkdownView Raw
1# async-exit-hook
2[![Build Status](https://api.travis-ci.org/Tapppi/async-exit-hook.svg)](https://travis-ci.org/Tapppi/async-exit-hook)
3[![Coverage Status](https://coveralls.io/repos/github/Tapppi/async-exit-hook/badge.svg?branch=master)](https://coveralls.io/github/Tapppi/async-exit-hook?branch=master)
4
5> Run some code when the process exits
6
7The `process.on('exit')` event doesn't catch all the ways a process can exit. This module catches:
8
9* process SIGINT, SIGTERM and SIGHUP, SIGBREAK signals
10* process beforeExit and exit events
11* PM2 clustering process shutdown message ([PM2 graceful reload](http://pm2.keymetrics.io/docs/usage/cluster-mode/#graceful-reload))
12
13Useful for cleaning up. You can also include async handlers, and add custom events to hook and exit on.
14
15Forked and pretty much rewritten from [exit-hook](https://npmjs.com/package/exit-hook).
16
17
18## Install
19
20```
21$ npm install --save async-exit-hook
22```
23
24## Usage
25
26### Considerations and warning
27#### On `process.exit()` and asynchronous code
28**If you use asynchronous exit hooks, DO NOT use `process.exit()` to exit.
29The `exit` event DOES NOT support asynchronous code.**
30>['beforeExit' is not emitted for conditions causing explicit termination, such as process.exit()]
31(https://nodejs.org/api/process.html#process_event_beforeexit)
32
33#### Windows and `process.kill(signal)`
34On windows `process.kill(signal)` immediately kills the process, and does not fire signal events,
35and as such, cannot be used to gracefully exit. See *Clustering and child processes* for a
36workaround when killing child processes. I'm planning to support gracefully exiting
37with async support on windows soon.
38
39### Clustering and child processes
40If you use custom clustering / child processes, you can gracefully shutdown your child process
41by sending a shutdown message (`childProc.send('shutdown')`).
42
43### Example
44```js
45const exitHook = require('async-exit-hook');
46
47exitHook(() => {
48 console.log('exiting');
49});
50
51// you can add multiple hooks, even across files
52exitHook(() => {
53 console.log('exiting 2');
54});
55
56// you can add async hooks by accepting a callback
57exitHook(callback => {
58 setTimeout(() => {
59 console.log('exiting 3');
60 callback();
61 }, 1000);
62});
63
64// You can hook uncaught errors with uncaughtExceptionHandler(), consequently adding
65// async support to uncaught errors (normally uncaught errors result in a synchronous exit).
66exitHook.uncaughtExceptionHandler(err => {
67 console.error(err);
68});
69
70// You can add multiple uncaught error handlers
71// Add the second parameter (callback) to indicate async hooks
72exitHook.uncaughtExceptionHandler((err, callback) => {
73 sendErrorToCloudOrWhatever(err, success => {
74 if (err) {
75 console.error('Error sending to cloud: ', err.stack);
76 } else {
77 console.log('Sent err to cloud');
78 }
79 callback();
80 });
81});
82
83// Add exit hooks for a signal or custom message:
84
85// Custom signal
86// Arguments are `signal, exitCode` (SIGBREAK is already handled, this is an example)
87exitHook.hookEvent('SIGBREAK', 21);
88
89// process event: `message` with a filter
90// filter gets all arguments passed to *handler*: `process.on(message, *handler*)`
91// Exits on process event `message` with msg `customShutdownMessage` only
92exitHook.hookEvent('message', 0, msg => msg !== 'customShutdownMessage');
93
94// All async hooks will work with uncaught errors when you have specified an uncaughtExceptionHandler
95throw new Error('awesome');
96
97//=> // Sync uncaughtExcpetion hooks called and retun
98//=> '[Error: awesome]'
99//=> // Sync hooks called and retun
100//=> 'exiting'
101//=> 'exiting 2'
102//=> // Async uncaughtException hooks return
103//=> 'Sent error to cloud'
104//=> // Sync uncaughtException hooks return
105//=> 'exiting 3'
106```
107
108
109## License
110
111MIT © Tapani Moilanen
112MIT © [Sindre Sorhus](http://sindresorhus.com)