Node.js脚本执行完毕后无法终止,疑为事件队列非空问题排查
脚本执行完终端挂起的原因及解决办法
问题根源
脚本执行完所有代码却挂起,是因为fetch请求创建的HTTP连接池残留了活跃句柄,卡住了Node.js的事件循环退出逻辑。
当你调用await getCall()时,fetch底层的HTTP客户端会自动创建连接池来复用TCP连接提升性能。即使请求已经处理完毕,这些空闲连接的句柄仍会留在事件循环里。再加上顶层await让模块变成异步执行模式,Node.js没法自动清理这些残留句柄,导致进程一直挂着不退出。而去掉await getCall()后没这个问题,就是因为没触发连接池的创建,事件循环里没有残留句柄,脚本跑完就正常退出了。
解决办法
1. 关闭fetch的连接复用(推荐)
给fetch配置自定义的Agent,关掉连接的长存活(keepAlive),这样请求结束后连接直接关闭,不会留在连接池里占着句柄。
修改后的getCall函数:
import * as child from "child_process"; import { Agent } from 'https'; // 接口是HTTP的话就用http.Agent async function getCall() { // 自定义Agent,禁用keepAlive const noKeepAliveAgent = new Agent({ keepAlive: false }); const endpoint = 'some-endpoint'; const response = await fetch(endpoint, { method: "GET", headers: { Authorization: "Bearer " + token, // 注意:这里token需要提前定义 "Content-Type": "application/json", }, agent: noKeepAliveAgent, // 绑定自定义Agent }); if (response.status !== 200) { const msg = `请求失败,状态码:${response.status}`; // 补充msg变量 console.error(msg); throw new Error(msg); } const json = await response.json(); return json; } // 后续代码不变...
2. 手动强制退出进程(简单直接)
如果确认所有任务都已经执行完毕,也可以在脚本最后加一行process.exit(),直接终止进程:
console.log('done'); console.log(process._getActiveRequests()); console.log(process._getActiveHandles().length); process.exit(); // 强制结束进程
3. 用完连接池后手动销毁
如果需要保留连接复用的特性,但想在脚本结束时清理连接池,可以在请求处理完后手动销毁Agent:
async function getCall() { const agent = new Agent({ keepAlive: true }); const endpoint = 'some-endpoint'; const response = await fetch(endpoint, { // 其他配置... agent: agent, }); // 请求处理完成后销毁Agent,清理所有连接 agent.destroy(); // 剩余逻辑... }
额外提醒
你的代码里token和msg两个变量没定义,实际运行会报错,记得补充上。
内容的提问来源于stack exchange,提问作者code share
相关产品推荐
相关产品推荐

