如何在Node上的http.request()设置超时?

我试图设置一个HTTP客户端使用http.request没有运气的超时。 到目前为止我所做的是这样的:

var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... } /* This does not work TOO MUCH... sometimes the socket is not ready (undefined) expecially on rapid sequences of requests */ req.socket.setTimeout(myTimeout); req.socket.on('timeout', function() { req.abort(); }); req.write('something'); req.end(); 

任何提示?

       

网上收集的解决方案 "如何在Node上的http.request()设置超时?"

使用你的代码,问题是在尝试设置套接字对象的东西之前,你还没有等待一个套接字被分配给请求。 这都是asynchronous的:

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... }); req.on('socket', function (socket) { socket.setTimeout(myTimeout); socket.on('timeout', function() { req.abort(); }); }); req.on('error', function(err) { if (err.code === "ECONNRESET") { console.log("Timeout occurs"); //specific error treatment } //other error treatment }); req.write('something'); req.end(); 

当请求分配一个套接字对象时,会触发'套接字'事件。

此时有一种方法直接对请求对象执行此操作:

 request.setTimeout(timeout, function() { request.abort(); }); 

这是绑定到套接字事件,然后创build超时的快捷方法。

参考: Node.js v0.8.8手册和文档

Rob Evans anwser对我来说工作正常,但是当我使用request.abort()时,它会抛出一个socket挂起错误,而这个错误一直处于未处理状态。

我不得不为请求对象添加一个error handling程序:

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... } req.on('socket', function (socket) { socket.setTimeout(myTimeout); socket.on('timeout', function() { req.abort(); }); } req.on('error', function(err) { if (err.code === "ECONNRESET") { console.log("Timeout occurs"); //specific error treatment } //other error treatment }); req.write('something'); req.end(); 

你应该通过参考请求如下

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... }); req.setTimeout(60000, function(){ this.abort(); }.bind(req); req.write('something'); req.end(); 

对我来说 – 这是一个不太令人困惑的做socket.setTimeout

 var request=require('https').get( url ,function(response){ var r=''; response.on('data',function(chunk){ r+=chunk; }); response.on('end',function(){ console.dir(r); //end up here if everything is good! }); }).on('error',function(e){ console.dir(e.message); //end up here if the result returns an error }); request.on('error',function(e){ console.dir(e); //end up here if a timeout }); request.on('socket',function(socket){ socket.setTimeout(1000,function(){ request.abort(); //causes error event ↑ }); }); 

好奇,如果你使用直接的net.sockets ,会发生什么? 下面是我为了testing目的而放置的一些示例代码:

 var net = require('net'); function HttpRequest(host, port, path, method) { return { headers: [], port: 80, path: "/", method: "GET", socket: null, _setDefaultHeaders: function() { this.headers.push(this.method + " " + this.path + " HTTP/1.1"); this.headers.push("Host: " + this.host); }, SetHeaders: function(headers) { for (var i = 0; i < headers.length; i++) { this.headers.push(headers[i]); } }, WriteHeaders: function() { if(this.socket) { this.socket.write(this.headers.join("\r\n")); this.socket.write("\r\n\r\n"); // to signal headers are complete } }, MakeRequest: function(data) { if(data) { this.socket.write(data); } this.socket.end(); }, SetupRequest: function() { this.host = host; if(path) { this.path = path; } if(port) { this.port = port; } if(method) { this.method = method; } this._setDefaultHeaders(); this.socket = net.createConnection(this.port, this.host); } } }; var request = HttpRequest("www.somesite.com"); request.SetupRequest(); request.socket.setTimeout(30000, function(){ console.error("Connection timed out."); }); request.socket.on("data", function(data) { console.log(data.toString('utf8')); }); request.WriteHeaders(); request.MakeRequest(); 

有更简单的方法。

而不是使用setTimeout或直接使用套接字,
我们可以在客户端使用“选项”中使用“超时”

下面是服务器和客户端的代码,分3部分。

模块和选项部分:

 'use strict'; // Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js const assert = require('assert'); const http = require('http'); const options = { host: '127.0.0.1', // server uses this port: 3000, // server uses this method: 'GET', // client uses this path: '/', // client uses this timeout: 2000 // client uses this, timesout in 2 seconds if server does not respond in time }; 

服务器部分:

 function startServer() { console.log('startServer'); const server = http.createServer(); server .listen(options.port, options.host, function () { console.log('Server listening on http://' + options.host + ':' + options.port); console.log(''); // server is listening now // so, let's start the client startClient(); }); } 

客户端部分:

 function startClient() { console.log('startClient'); const req = http.request(options); req.on('close', function () { console.log("got closed!"); }); req.on('timeout', function () { console.log("timeout! " + (options.timeout / 1000) + " seconds expired"); // Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js#L27 req.destroy(); }); req.on('error', function (e) { // Source: https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js#L248 if (req.connection.destroyed) { console.log("got error, req.destroy() was called!"); return; } console.log("got error! ", e); }); // Finish sending the request req.end(); } startServer(); 

如果将上述3个部分放在一个文件“a.js”中,然后运行:

 node a.js 

那么,输出将是:

 startServer Server listening on http://127.0.0.1:3000 startClient timeout! 2 seconds expired got closed! got error, req.destroy() was called! 

希望有所帮助。