在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
您可以在setTimeout
callback中使用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
清除调用堆栈(请参阅此问题 ),因此您不必担心setTimeout
recursion调用的堆栈溢出问题。
使用生成器(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秒 。