下面的代码执行一个长时间运行的函数(一个睡眠以保持简单),然后使用setTimeout再次回调自身。我正在使用nodejs 5.1.0
var start_time = Math.ceil(new Date() /1000)
function sleep(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}
function iteration(){
console.log("sleeping at :", Math.ceil(new Date()/1000 - start_time));
sleep(10000); // sleep 10 secs
console.log("waking up at:", Math.ceil(new Date()/1000 - start_time));
setTimeout(iteration, 0);
}
iteration();
在调用setTimeout的那一刻节点没有做任何事情(理论上事件循环为空?)所以我希望立即执行回调。换句话说,我希望程序在唤醒后立即进入睡眠状态。
然而,这是发生的事情:
>iteration();
sleeping at : 0
waking up at: 10
undefined
> sleeping at : 10 //Expected: Slept immediately after waking up
waking up at: 20
sleeping at : 30 //Not expected: Slept 10 secs after waking up
waking up at: 40
sleeping at : 50 //Not expected: Slept 10 secs after waking up
waking up at: 60
sleeping at : 70 //Not expected. Slept 10 secs after waking up
waking up at: 80
sleeping at : 90 //Not expected: Slept 10 secs after waking up
waking up at: 100
sleeping at : 110 //Not expected: Slept 10 secs after waking up
正如您所看到的,程序在第一次唤醒后立即睡眠(这是我所期望的),但之后却没有。事实上,它在醒来和睡觉之间等待了10秒。
如果我使用setImmediate,一切正常。知道我错过了什么吗?
编辑:
注意:
1-在我的实际代码中,我有一个复杂的长算法而不是一个简单的睡眠函数。上面的代码只是在一个更简单的用例中重现了这个问题。 这意味着我无法使用setTimeout(iteraton,10000)
2-我使用延迟为0的setTimeout的原因是因为我的代码阻塞了nodejs很长时间以至于其他较小的任务被延迟了。通过执行setTimeout,nodejs返回事件循环以执行那些小任务,然后继续处理我的主要长期运行代码
3-我完全理解setInterval(function,0)将尽快运行,而不是立即运行,但这并不能解释为什么它运行10秒延迟,因为nodejs没有做任何其他事情
4- Chrome中的代码运行没有任何问题。 Nodejs bug?
答案 0 :(得分:0)
首先看一下node.js documenation:
请务必注意,您的回调可能不会被调用 在完全延迟毫秒 - Node.js不保证 回调将触发的确切时间,也不是排序 事情会发生。回调将尽可能接近 到指定的时间。
为了使你的功能更加异步,你可以做出类似的事情:
function iteration(callback){
console.log("sleeping at :", Math.ceil(new Date()/1000));
sleep(10000); // sleep 10 secs
console.log("waking up at:", Math.ceil(new Date()/1000));
return setTimeout(callback(iteration), 0);
}
iteration(iteration);
下一个问题是你的睡眠功能。你有一个while循环阻塞你所有的node.js进程,以便为你创建node.js的setTimeout函数。
function sleep(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}
现在发生的事情是你的睡眠功能正在阻止这个过程。当你在setTimeout的异步调用之后,通过node.js初始化函数的范围时,不仅在你直接调用函数时也会发生这种情况。
这不是一个错误。它必须是这样的,因为在你的while循环内部可能是你的迭代函数必须知道的东西。特别是在setTimeout之后调用它。因此,首先检查睡眠功能,并尽快调用该函数。
问题更改后编辑的答案