节点http.request,如果发送请求后互联网停止,则不会触发任何事件

Jix*_*xun 5 client http request node.js

我在服务器上有以下 PHP 脚本,它将等待 10 秒并说Hello

<php sleep(10); ?>Hello
Run Code Online (Sandbox Code Playgroud)

在客户端(节点),我有以下内容:

var http = require('http');
http.get ('http://example.com/sleep.php', function (resp) {
    resp.on('data', function (d) {
        console.log ('data!', d.toString());
    });
    resp.on('end', function (d) {
        console.log ('Finished!');
    });
}).on('error', function (e) {
    console.log ('error:', e);
});
Run Code Online (Sandbox Code Playgroud)

问题是,如果在请求期间互联网连接停止,则不会触发errorORend事件。

要重现问题:

  • 将 PHP 脚本放置在 Internet 上的某个位置
  • 执行节点脚本
  • 断开互联网连接
  • 该脚本不执行任何操作

我还发现,如果连接在 10 秒内恢复,它仍然可以接收消息。

因此,我做了一个简单的间隔循环来检查状态。但是它无法检测连接是否已停止工作或仍在等待响应:

var http = require('http');
var lastRespond = 0, intervalCheck;
var respFinished = false;
http.get ('http://jixun.no-ip.org/sleep.php', function (resp) {
    resp.on('data', function (d) {
        lastRespond = new Date;
        console.log ('data!', d.toString());
    });
    resp.on('end', function (d) {
        respFinished = true;
        console.log ('Finished!');
    });
}).on('error', function (e) {
    console.log ('error:', e);
});
intervalCheck = setInterval(function () {
    if (respFinished) {
        clearInterval(intervalCheck);
    } else if (new Date - lastRespond >= 120000) {
        console.log ('Timeout   :(');
        clearInterval(intervalCheck);
    }
}, 120000); // 2 mins.
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:有什么方法可以检查发送请求后套接字是否关闭/连接是否停止?提前致谢。

fre*_*sla 3

在实际请求上使用 setTimeout 可以解决您的问题。嗯,这不是像“关闭”、“结束”和“错误”这样的实际事件。下面的示例确实重现并解决了问题,但尚未在其他情况下尝试过。

var http = require('http'); 
http.get ('http://fake-response.appspot.com?sleep=5', function (resp) { 
  resp.on('data', function (d) {
    console.log ('data!', d.toString()); 
  }); 
  resp.on('end', function (d) { 
     console.log ('Finished!'); 
  }); 
}).on('error', function (e) {
    console.log ('error:', e); 
}).setTimeout(12000, function ( ) { 
    console.log('Timeout reached...'); 
    process.exit(1);
});        
Run Code Online (Sandbox Code Playgroud)

更多信息可以在文档中找到。要么使用它,要么监听“close”事件,这与 net 模块配合得很好。