setTimeout在长时间运行的函数中引入延迟

下面的代码执行一个长时间运行的函数(一个简单的睡眠),然后使用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被调用的时刻,node没有做任何事情(理论上eventloop为空),所以我期望这个callback立即执行。 换句话说,我希望程序在醒来后立即睡觉。

但是,这是发生了什么:

 >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-在我的真实代码中,我有一个复杂的长algorithm,而不是一个简单的睡眠函数。 上面的代码只是在一个更简单的用例中重现了这个问题。 这意味着我不能使用setTimeout(iteraton,10000)

我使用setTimeout延迟为0的原因是因为我的代码长时间阻塞nodejs,导致其他较小的任务延迟。 通过执行setTimeout,nodejs返回到事件循环来执行这些小任务,然后继续处理我的主要长时间运行的代码

我完全理解,setInterval(function,0)会尽快运行,不会立即运行,但是这并不能解释为什么它运行10秒,因为nodejs没有做任何事情

我在Chrome中的代码运行没有任何问题。 Nodejs的错误?

首先看一下node.js文件 :

重要的是要注意,你的callback可能不会被精确地延迟几毫秒 – Node.js不能确保callback触发的确切时间,也不会触发sorting的东西。callback将被称为尽可能接近指定的时间。

为了使你的function更加asynchronous,你可以做一些事情:

 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); 

接下来的问题是你的睡眠function。 你有一个while循环阻塞了你所有的node.js进程,使得node.js的setTimeout函数为你做了一些事情。

 function sleep(delay) { var start = new Date().getTime(); while (new Date().getTime() < start + delay); } 

现在发生的事情是你的睡眠function阻止了这个过程。 当你直接调用这个函数的时候,它不仅会发生,而且在setTimeout的asynchronous调用之后,函数的作用域被node.js初始化。

这不是一个错误。 它必须是这样的,因为在你的while循环里可能是迭代函数必须知道的东西。 特别是在setTimeout之后被调用的时候。 所以首先检查睡眠function,并尽快调用该function。

问题变更后编辑回答