Express中是否存在Fastify.addHook('onClose', () => {})的等价实现?
Express应用退出时执行操作的多种解决方案
除了你已经尝试的process.on('exit'),还有几种更灵活的方案,适合不同场景下的优雅退出和资源清理:
1. 监听系统终止信号(SIGINT/SIGTERM)
process.exit事件触发时,Node.js已经进入退出流程,异步操作可能无法完成。监听系统信号可以提前捕获退出请求,执行异步清理后再主动退出:
const server = app.listen(3000); // 捕获Ctrl+C触发的SIGINT信号 process.on('SIGINT', async () => { console.log('收到终止信号,开始优雅退出'); // 先停止HTTP服务器,拒绝新请求,处理完现有请求 server.close(async () => { console.log('HTTP服务器已停止'); // 执行异步清理:关闭数据库连接、释放文件锁等 await dbConnection.close(); await releaseResources(); console.log('清理完成,应用退出'); process.exit(0); }); }); // 捕获系统发送的SIGTERM信号(如Docker stop、systemd stop) process.on('SIGTERM', async () => { console.log('收到系统终止信号'); await gracefulShutdown(server); process.exit(0); }); // 封装优雅退出逻辑 async function gracefulShutdown(server) { server.close(); await dbConnection.close(); console.log('资源已全部释放'); }
2. 监听HTTP服务器的close事件
如果你需要在HTTP服务器完全关闭后执行操作,可以直接监听server实例的close事件:
const server = app.listen(3000); server.on('close', () => { console.log('HTTP服务器已关闭,所有现有请求处理完成'); // 这里可以做同步清理操作 clearInterval(heartbeatInterval); console.log('定时任务已清除'); }); // 需要主动调用server.close()才会触发close事件,通常结合信号监听 process.on('SIGINT', () => { server.close(); });
3. 处理异常退出场景
针对未捕获的异常或未处理的Promise拒绝,也可以添加监听来执行紧急清理:
// 捕获未捕获的同步异常 process.on('uncaughtException', (err) => { console.error('未捕获异常:', err.stack); // 紧急清理(尽量用同步操作,避免异步不确定性) fs.writeFileSync('crash.log', `崩溃时间: ${new Date()}\n错误信息: ${err.stack}`); process.exit(1); }); // 捕获未处理的Promise拒绝 process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); // 执行必要清理后退出 process.exit(1); });
4. 第三方工具简化(可选)
如果不想手动管理多个信号监听,可以用exit-hook这类库帮你统一处理退出逻辑:
const exitHook = require('exit-hook'); // 注册同步清理 exitHook(() => { console.log('应用即将退出,执行同步清理'); }); // 注册异步清理 exitHook(async () => { await dbConnection.close(); console.log('数据库连接已关闭'); });
这个库会自动监听SIGINT、SIGTERM等信号,以及process.exit事件,无需手动绑定每个信号。
内容的提问来源于stack exchange,提问作者Mark G
相关产品推荐
相关产品推荐

