node.js - setTimeout 在长时间运行的函数中引入延迟

标签 node.js

下面的代码执行一个长时间运行的函数(为了保持简单而进行 sleep ),然后使用 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 为空?),因此我希望立即执行该回调。换句话说,我希望程序在醒来后立即进入休眠状态。

但是发生的事情是这样的:

>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

正如您所看到的,程序在第一次唤醒后立即休眠(这是我所期望的),但之后就不再休眠了。事实上,它在醒来和 sleep 之间又等待了 10 秒。

如果我使用 setImmediate 一切正常。知道我缺少什么吗?

编辑:

注释:

1-在我的真实代码中,我有一个复杂的长算法,而不是一个简单的 sleep 函数。上面的代码只是在更简单的用例中重现了问题。 这意味着我无法使用 setTimeout(iteraton, 10000)

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

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

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

最佳答案

首先看node.js documenation :

It is important to note that your callback will probably not be called in exactly delay milliseconds - Node.js makes no guarantees about the exact timing of when the callback will fire, nor of the ordering things will fire in. The callback will be called as close as possible to the time specified.

为了使你的函数更加异步,你可以这样做:

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

下一个问题是你的 sleep 功能。您有一个 while 循环阻塞所有的 Node.js 进程,以便让 Node.js 的 setTimeout 函数为您做一些事情。

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

现在发生的情况是您的 sleep 功能正在阻止该进程。这种情况不仅发生在直接调用函数时,也会发生在通过 Node.js 异步调用 setTimeout 之后初始化函数的作用域时。

这不是一个错误。它必须是这样的,因为在 while 循环内部可能是迭代函数必须知道的东西。特别是在 setTimeout 之后调用它时。因此,首先检查 sleep 函数,并尽快调用该函数。

问题更改后编辑答案

关于node.js - setTimeout 在长时间运行的函数中引入延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34201827/

相关文章:

node.js - 如何使用 Chai Http 发布对象数组

php - 使用 Node.js 在 PHP 应用程序中显示消息的实时通知

node.js - 是否可以检查消息是否不包含 "ew"并删除该消息?

node.js - Vuesax 4 错误 : Cannot find module 'chalk'

node.js - 管理多个 TCP 套接字 nodejs

javascript - 如何正确排序我的评论/回复/对回复数据的回复

javascript - 创建锁,这样两个用户就不会使用相同的用户名创建帐户

Mysql 返回不正确的 bigint 结果 1,非常奇怪的错误

javascript - 如何处理交易错误?

android - 在 Firebase 控制台上查看发送的消息