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

如何确保Node.js HTTP客户端在ECONNRESET后仅触发一次回调

解决Node.js HTTP客户端连接重置时同时触发error和end回调的问题

问题描述

基于Node.js http模块编写的HTTP客户端代码,预期只会触发success!或error!其中一个逻辑,但当服务器返回响应头后TCP连接被重置(如ECONNRESET错误)时,两个回调会同时触发,导致业务逻辑重复执行。

原代码示例:

var http = require('http');
http.get('http://127.0.0.1:12345/', function(response) {
    console.log('got response ', response.statusCode);
    var body = [];
    response.on('data', function(data) {
        console.log('got data: ', data);
    });
    response.on('end', function() {
        body = Buffer.concat(body).toString();
        console.log('end body = ', body, ' complete = ', response.complete);
        console.log('success!');
    });
}).on('error', function(err) {
    console.log('ClientRequest error: ' + err);
    console.log('error!');
});

问题场景:服务器返回响应头和部分/全部响应体后,TCP连接被强制断开,此时客户端会同时触发ClientRequest的error事件和response的end事件,导致success!和error!同时打印。

解决方案

核心思路是通过状态标记避免重复执行,同时结合response.complete判断响应是否完整接收,确保只有真正的成功场景才触发业务成功逻辑。

修改后的代码:

var http = require('http');

// 标记请求是否已处理完成,防止重复执行回调逻辑
let isCompleted = false;

const req = http.get('http://127.0.0.1:12345/', function(response) {
    console.log('got response ', response.statusCode);
    const body = [];
    
    response.on('data', function(data) {
        console.log('got data: ', data);
        body.push(data); // 修复原代码遗漏的data存入逻辑
    });
    
    response.on('end', function() {
        if (isCompleted) return;
        
        // 仅当响应完全接收时,才判定为请求成功
        if (response.complete) {
            const fullBody = Buffer.concat(body).toString();
            console.log('end body = ', fullBody, ' complete = ', response.complete);
            console.log('success!');
        } else {
            console.log('incomplete response received, error!');
        }
        isCompleted = true;
    });
});

req.on('error', function(err) {
    if (isCompleted) return;
    
    // 若响应已完整接收,后续的连接重置错误不影响业务结果,直接忽略
    if (req.res && req.res.complete) {
        console.log('connection reset after full response received, ignore error');
        isCompleted = true;
        return;
    }
    
    console.log('ClientRequest error: ' + err);
    console.log('error!');
    isCompleted = true;
});

关键逻辑说明

  1. 状态锁isCompleted:无论error或end事件哪个先触发,都会先检查该标记,已处理过的请求直接跳过后续逻辑,从根源避免重复执行。
  2. 响应完整性校验:在end回调中通过response.complete判断响应是否完整接收,确保只有全部数据都收到时才触发成功逻辑。
  3. 错误过滤:在error回调中,若发现响应已完整接收(req.res.complete为true),说明业务数据已经获取完成,此时的连接重置错误无需触发业务失败逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 06:12:46