{"id":13622552,"url":"https://github.com/Tapppi/async-exit-hook","last_synced_at":"2025-04-15T09:32:54.962Z","repository":{"id":49539809,"uuid":"53319848","full_name":"Tapppi/async-exit-hook","owner":"Tapppi","description":"Run some code when the process exits","archived":false,"fork":true,"pushed_at":"2021-06-15T13:34:48.000Z","size":90,"stargazers_count":118,"open_issues_count":11,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-31T00:50:35.876Z","etag":null,"topics":["async","es6","exit","node","process","sigint","signal","sigterm"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"sindresorhus/exit-hook","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tapppi.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-07T11:18:27.000Z","updated_at":"2024-06-13T01:15:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Tapppi/async-exit-hook","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapppi%2Fasync-exit-hook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapppi%2Fasync-exit-hook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapppi%2Fasync-exit-hook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tapppi%2Fasync-exit-hook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tapppi","download_url":"https://codeload.github.com/Tapppi/async-exit-hook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223668215,"owners_count":17182893,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","es6","exit","node","process","sigint","signal","sigterm"],"created_at":"2024-08-01T21:01:21.007Z","updated_at":"2024-11-08T10:30:29.871Z","avatar_url":"https://github.com/Tapppi.png","language":"JavaScript","readme":"# async-exit-hook\n[![Build Status](https://api.travis-ci.org/Tapppi/async-exit-hook.svg)](https://travis-ci.org/Tapppi/async-exit-hook)\n[![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)\n\n\u003e Run some code when the process exits\n\nThe `process.on('exit')` event doesn't catch all the ways a process can exit. This module catches:\n\n* process SIGINT, SIGTERM and SIGHUP, SIGBREAK signals  \n* process beforeExit and exit events  \n* PM2 clustering process shutdown message ([PM2 graceful reload](http://pm2.keymetrics.io/docs/usage/cluster-mode/#graceful-reload))  \n\nUseful for cleaning up. You can also include async handlers, and add custom events to hook and exit on.\n\nForked and pretty much rewritten from [exit-hook](https://npmjs.com/package/exit-hook).\n\n\n## Install\n\n```\n$ npm install --save async-exit-hook\n```\n\n## Usage\n\n### Considerations and warning\n#### On `process.exit()` and asynchronous code\n**If you use asynchronous exit hooks, DO NOT use `process.exit()` to exit.\nThe `exit` event DOES NOT support asynchronous code.**\n\u003e['beforeExit' is not emitted for conditions causing explicit termination, such as process.exit()]\n(https://nodejs.org/api/process.html#process_event_beforeexit)\n\n#### Windows and `process.kill(signal)`\nOn windows `process.kill(signal)` immediately kills the process, and does not fire signal events, \nand as such, cannot be used to gracefully exit. See *Clustering and child processes* for a\nworkaround when killing child processes. I'm planning to support gracefully exiting \nwith async support on windows soon.\n\n### Clustering and child processes\nIf you use custom clustering / child processes, you can gracefully shutdown your child process\nby sending a shutdown message (`childProc.send('shutdown')`).\n\n### Example\n```js\nconst exitHook = require('async-exit-hook');\n\nexitHook(() =\u003e {\n    console.log('exiting');\n});\n\n// you can add multiple hooks, even across files\nexitHook(() =\u003e {\n    console.log('exiting 2');\n});\n\n// you can add async hooks by accepting a callback\nexitHook(callback =\u003e {\n    setTimeout(() =\u003e {\n        console.log('exiting 3');\n        callback();\n    }, 1000);\n});\n\n// You can hook uncaught errors with uncaughtExceptionHandler(), consequently adding \n// async support to uncaught errors (normally uncaught errors result in a synchronous exit).\nexitHook.uncaughtExceptionHandler(err =\u003e {\n    console.error(err);\n});\n\n// You can hook unhandled rejections with unhandledRejectionHandler()\nexitHook.unhandledRejectionHandler(err =\u003e {\n    console.error(err);\n});\n\n// You can add multiple uncaught error handlers\n// Add the second parameter (callback) to indicate async hooks\nexitHook.uncaughtExceptionHandler((err, callback) =\u003e {\n    sendErrorToCloudOrWhatever(err) // Returns promise\n        .then(() =\u003e {\nconsole.log('Sent err to cloud');\n        })\n        .catch(sendError =\u003e {\nconsole.error('Error sending to cloud: ', err.stack);\n        })\n        .then(() =\u003e callback);\n});\n\n// Add exit hooks for a signal or custom message:\n\n// Custom signal\n// Arguments are `signal, exitCode` (SIGBREAK is already handled, this is an example)\nexitHook.hookEvent('SIGBREAK', 21);\n\n// process event: `message` with a filter\n// filter gets all arguments passed to *handler*: `process.on(message, *handler*)`\n// Exits on process event `message` with msg `customShutdownMessage` only\nexitHook.hookEvent('message', 0, msg =\u003e msg !== 'customShutdownMessage');\n\n// All async hooks will work with uncaught errors when you have specified an uncaughtExceptionHandler\nthrow new Error('awesome');\n\n//=\u003e // Sync uncaughtExcpetion hooks called and retun\n//=\u003e '[Error: awesome]'\n//=\u003e // Sync hooks called and retun\n//=\u003e 'exiting'\n//=\u003e 'exiting 2'\n//=\u003e // Async uncaughtException hooks return\n//=\u003e 'Sent error to cloud'\n//=\u003e // Sync uncaughtException hooks return\n//=\u003e 'exiting 3'\n```\n\n\n## License\n\nMIT © Tapani Moilanen  \nMIT © [Sindre Sorhus](http://sindresorhus.com)\n","funding_links":[],"categories":["es6","node"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTapppi%2Fasync-exit-hook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTapppi%2Fasync-exit-hook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTapppi%2Fasync-exit-hook/lists"}