在Node.js循环中设置setTimeout

对于setTimeout是如何工作的,我有点困惑。 我试图在一个循环中有一个setTimeout ,以便循环迭代相隔1秒。 每个循环迭代都会产生一个HTTP请求,而另一端的服务器似乎不能在如此短的时间内处理这么多的请求。

 for (var i = 1; i<=2000 && ok; i++) { var options = { host:'www.host.com', path:'/path/'+i }; setTimeout(makeRequest(options, i), 1000); }; 

为什么这不起作用,我怎么能做到这一点?

谢谢

你需要这样的东西

 var counter = 5; function makeRequst(options, i) { // do your request here } function myFunction() { alert(counter); // create options object here //var options = { // host:'www.host.com', // path:'/path/'+counter //}; //makeRequest(options, counter); counter--; if (counter > 0) { setTimeout(myFunction, 1000); } } 

另见这个小提琴

alert(count);alert(count); 你可以打电话给服务器。 请注意,计数器正好相反(倒数)。 我更新了一些评论在哪里做你的事情。

setTimeout是非阻塞的 ,它是asynchronous的。 你给它一个callback,当延迟结束时,你的callback被调用。

这里有一些实现:

使用recursion

您可以在setTimeoutcallback中使用recursion调用 。

 function waitAndDo(times) { if(times < 1) { return; } setTimeout(function() { // Do something here console.log('Doing a request'); waitAndDo(times-1); }, 1000); } 

这里是如何使用你的function:

 waitAndDo(2000); // Do it 2000 times 

关于堆栈溢出错误setTimeout清除调用堆栈(请参阅此问题 ),因此您不必担心setTimeoutrecursion调用的堆栈溢出问题。

使用生成器(io.js,ES6)

如果您已经在使用io.js (使用ES6的“下一个”Node.js),则可以使用优雅的解决scheme无需recursion即可解决问题:

 function* waitAndDo(times) { for(var i=0; i<times; i++) { // Sleep yield function(callback) { setTimeout(callback, 1000); } // Do something here console.log('Doing a request'); } } 

这里是如何使用你的function(与公司 ):

 var co = require('co'); co(function* () { yield waitAndDo(10); }); 

顺便说一句:这是真的使用循环;)

发电机function文件 。

你在你的setTimeout调用中调用了makeRequest(),你应该把这个函数传给setTimeout,而不是调用它,

 setTimeout(makeRequest, 1000); 

没有()

现在,您正在安排所有请求在脚本运行后的一秒内同时发生。 你需要做如下的事情:

 var numRequests = 2000, cur = 1; function scheduleRequest() { if (cur > numRequests) return; makeRequest({ host: 'www.host.com', path: '/path/' + cur }, cur); cur++; setTimeout(scheduleRequest, 1000) } 

请注意,每个后续请求只在当前的请求完成后才被调度。

我可能会在派对上迟到,但这里是另一个(更可读的)解决scheme,而不需要省略循环。

你的代码所做的是创build2000(实际上是1999)的setTimeout对象, 从现在起 1秒后将调用makeRequest函数。 看,他们都不知道另一个setTimeout的存在。

如果你想让它们彼此隔开1秒,你有责任创造它们。

这可以通过使用您的计数器 (在这种情况下)和超时延迟来实现

 for (var i = 1; i<=2000 && ok; i++) { var options = { host:'www.host.com', path:'/path/'+i }; setTimeout(makeRequest(options, i), i * 1000); //Note i * 1000 }; 

第一个超时对象从现在开始设置为1秒第二个从现在开始设置为2秒 ,依此类推; 意思是相隔1秒