如何在Node中设置http.request()的超时时间?
我试图设置HTTP客户端上使用http.request没有运气的超时。到目前为止我做的是这样的:如何在Node中设置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();
任何提示?
好奇,如果您直接使用net.sockets
,会发生什么情况?下面是一些示例代码,我放在一起测试目的:
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();
使用你的代码,问题是你有没有等待一个插座,以试图设置的东西Socket对象之前被分配到请求。它们都是异步的:
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();
当请求被分配一个套接字对象时,会触发'套接字'事件。
这确实是完全有意义的。问题是,现在我无法测试这个特定问题(时间流逝......)。所以我现在只能赞扬答案:)谢谢。 – Claudio 2012-03-29 13:07:28
不用担心。请记住,据我所知,这只适用于最新版本的节点。我测试了以前的版本(5.0.3-pre),我认为它并没有触发套接字事件。 – 2012-03-29 16:21:31
处理这个问题的另一种方法是使用一个bog标准的setTimeout调用。你需要保持setTimeout id为:var id = setTimeout(...);这样你可以取消它,如果你收到一个数据等。一个好方法是将它存储在请求对象本身,然后clearTimeout,如果你有一些数据。 – 2012-03-29 16:23:45
这时有直接请求对象上做到这一点的方法:
request.setTimeout(timeout, function() {
request.abort();
});
这是结合到插座事件的快捷方式,然后创建超时。
中正确处理超时。request.setTimeout“将套接字上的非活动超时毫秒数设置为超时。 “我认为这个问题是关于不考虑活动而超时的。 – ostergaard 2013-01-20 14:00:18
请注意,与直接使用相关套接字的答案相同,req.abort()会导致一个错误事件,该事件应该由on('error')处理。 – KLoozen 2016-01-10 17:31:29
request.setTimeout不会放弃请求,我们需要在超时回调中手动调用放弃。 – Udhaya 2016-02-23 05:52:04
的罗布·埃文斯anwser工作正常但对我来说,当我使用request.abort(),它发生抛出一个插座挂断错误,保持未处理。
我不得不添加一个错误处理程序请求对象:
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();
“myTimeout”函数在哪里? (编辑:文档说:与绑定到超时事件相同https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback) – 2016-09-20 21:08:22
请注意,'ECONNRESET'可以发生在两种情况:客户端关闭套接字和服务器关闭连接。要通过调用'abort()'来确定它是否由客户端完成,那么会出现“abort”事件 – Derp 2016-11-08 09:16:37
您应该通过参考请求像下面
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();
请求错误事件会得到触发
req.on("error", function(e){
console.log("Request Error : "+JSON.stringify(e));
});
我 - 这里是做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 ↑
});
});
有更简单的方法的不易混淆的方式。
而不是使用的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个部分在一个文件中,“一.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!
希望有所帮助。
找到了这个答案(它也可以),但我不知道是否有什么不同的http.request()http://stackoverflow.com/questions/6129240/how-to-set-timeout-for-http-createclient -in-node-js – Claudio 2011-06-02 13:22:29