如何保证在 ECONNRESET 之后在一个简单的 Node.js HTTP 客户端中恰好触发一个回调,而不是两次?

问题描述 投票:0回答:1

考虑以下 HTTP 客户端,以下

http
模块的官方示例`

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!');
});

这里我发出一个 HTTP 请求,并在三种情况下报告:每当我开始接收 HTTP 响应时,每当我收到一些 HTTP 正文数据时,当响应完成时,以及所有错误时。

我希望此代码始终完成(除非连接挂起),日志中正好有一个

success!
error!
。但是,如果在服务器已经发送了一些标头之后连接重置,我会得到both。这是一个示例输出:

got response  200
got data:  <Buffer 48 65 6c 6c 6f 0a>
ClientRequest error: Error: read ECONNRESET
error!
end body =  Hello
  complete =  true
success!

如何复制:

  1. nc -l -p 12345
    启动调试服务器。
  2. node a.js
    运行客户端。我在 Windows 上使用
    node v18.14.2
    ,但我在 Ubuntu 22.04 上也看到了相同的行为
    node v12.22.9
  3. 键入以下响应,但不要中止
    nc
    HTTP/1.1 200 OK
    
    Hello
    
  4. 使用任务管理器(Windows)终止
    nc
    进程或使用
    sudo tcpkill -i lo port 12345
    终止TCP连接并向
    nc
    (Linux)写入其他内容。

似乎 Node 既检测到错误(因此

error
回调被触发)并认为 HTTP 请求成功(因此
end
回调被触发)。在我的原始代码中,导致我的应用程序的两个实例继续运行,而不是一个非常混乱。

如何确保其中一个被触发,并且仅在成功的 HTTP 响应时触发?

javascript node.js http callback econnreset
1个回答
0
投票

我建议看一下 once() 函数,它在被调用后会自行删除,这是它的参考链接 - https://nodejs.org/api/events.html#emitteronceeventname-listener

© www.soinside.com 2019 - 2024. All rights reserved.