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

Node.js中如何关闭stdin?请求回调未触发致脚本挂起问题

解决Node.js http.request脚本挂起的问题

嘿,我之前踩过一模一样的坑!咱们来拆解下为啥你的脚本会一直卡着,以及怎么把它搞定。

首先,核心问题大概率出在请求流没被正确收尾,或者事件循环里还有未处理的活跃资源,导致Node.js进程没法自动退出。

常见原因&解决方案

1. 显式结束请求流(最关键)

虽然process.stdin.pipe(req)看起来会自动处理流的结束,但在某些场景下(比如stdin的end事件触发时机和请求流缓冲区的同步问题),请求并没有真正完成发送。你需要在stdin结束后手动调用req.end(),明确告诉服务器“我所有数据都发完了”:

const http = require('http');

const req = http.request({
  hostname: 'localhost',
  port: 3000,
  method: 'POST'
}, (res) => {
  console.log('Works');
  // 监听响应结束,确保进程能正常退出
  res.on('end', () => {
    process.exit();
  });
});

// 将stdin内容pipe到请求
process.stdin.pipe(req);

// 关键:stdin结束后显式结束请求流
process.stdin.on('end', () => {
  req.end();
});

2. 捕获请求错误,避免静默挂起

很多时候脚本挂起是因为发生了错误但没被捕获(比如连接超时、服务器拒绝连接),这些错误会让请求流卡住,但不会主动终止进程。给req加上错误监听:

req.on('error', (err) => {
  console.error('请求出错啦:', err.message);
  process.exit(1);
});

3. 检查服务器端是否正确响应

如果客户端代码没问题,那可能是服务器端没正确结束响应流。确保你的服务器在处理完请求后调用了res.end(),比如:

// 服务器端示例代码
const http = require('http');
const server = http.createServer((req, res) => {
  // 这里写你的请求处理逻辑
  res.end('处理完成'); // 必须调用end来结束响应
});
server.listen(3000);

原理补充

Node.js的事件循环会在存在活跃的流、定时器或未处理的Promise时保持运行。如果你的请求流没结束,或者响应流没被完全消费,进程就会一直挂着。所以:

  • 显式调用req.end()确保请求发送完成
  • 监听res.end()并调用process.exit()(或者消费完响应数据),让事件循环能正常退出

内容的提问来源于stack exchange,提问作者Sukima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:48:34