You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:55:30