setTimeout如何在Node.JS中工作?

时间:2011-05-01 14:54:12

标签: javascript node.js serverside-javascript

我想一旦它被执行了它就在队列中,但在队列中是否有任何保证它会在X毫秒后完全调用?或者队列中其他较重的任务会延迟吗?

5 个答案:

答案 0 :(得分:154)

setTimeout的语义与Web浏览器中的语义大致相同:timeout arg是最小执行前等待的ms数,而不是保证。此外,传递0,非数字或负数将使其等待最小数量的ms。在Node中,这是1ms,但在浏览器中它可以长达50ms。

原因是JavaScript没有抢占JavaScript。考虑这个例子:

setTimeout(function () {
  console.log('boo')
}, 100)
var end = Date.now() + 5000
while (Date.now() < end) ;
console.log('imma let you finish but blocking the event loop is the best bug of all TIME')

这里的流程是:

  1. 安排超时100毫秒。
  2. busywait for 5000ms。
  3. 返回事件循环。检查挂起的计时器并执行。
  4. 如果不是这种情况,那么你可以让一点JavaScript“中断”另一个。我们必须设置互斥和信号等,以防止这样的代码极难推理:

    var a = 100;
    setTimeout(function () {
      a = 0;
    }, 0);
    var b = a; // 100 or 0?
    

    Node的JavaScript执行的单线程性使得它比大多数其他样式的并发更简单。当然,权衡的是程序中一个表现不好的部分可能会以无限循环阻塞整个事物。

    这是一个比先发制人的复杂性更好的战斗恶魔吗?这取决于。

答案 1 :(得分:40)

非阻塞的想法是循环迭代很快。因此,为每个tick进行迭代应该花费足够短的时间,使setTimeout精确到合理的精度(可能<100 ms左右)。

理论上虽然你是对的。如果我编写一个应用程序并阻止勾选,那么setTimeouts将被延迟。那么回答你的问题,谁可以保证setTimeouts按时执行?通过编写非阻塞代码,您可以将精度控制在几乎任何合理的准确度范围内。

只要javascript在代码执行方面是“单线程”(不包括网络工作者等),这将永远发生。在大多数情况下,单线程性质是一个巨大的简化,但需要非阻塞成语才能成功。

在您的浏览器或节点中尝试使用此代码,您将看到无法保证准确性,相反,setTimeout将会很晚:

var start = Date.now();

// expecting something close to 500
setTimeout(function(){ console.log(Date.now() - start); }, 500);

// fiddle with the number of iterations depending on how quick your machine is
for(var i=0; i<5000000; ++i){}

除非解释器优化循环(它不在chrome上),否则你将获得成千上万的东西。移除循环,你会看到它的鼻子是500 ......

答案 2 :(得分:8)

确保代码执行的唯一方法是将setTimeout逻辑放在不同的进程中。

使用子进程模块生成一个新的node.js程序,该程序执行您的逻辑并通过某种流(可能是tcp)将数据传递给该进程。

这种方式即使你的主进程中运行了一些长阻塞代码,你的子进程也已经启动了,并将setTimeout放在一个新进程和一个新线程中,因此会在你期望的时候运行。

进一步的复杂性是在硬件级别,你有更多的线程运行然后进程,因此上下文切换将导致(非常小的)预期时间延迟。这应该是可以忽略不计的,如果它很重要,你需要认真考虑你想要做什么,为什么你需要这样的准确性以及可以用什么样的实时替代硬件来完成这项工作。

通常,使用子进程并将多个节点应用程序作为单独的进程与负载均衡器或共享数据存储(如redis)一起运行对于扩展代码非常重要。

答案 3 :(得分:6)

setTimeout 是一种线程,它保存给定时间的操作并执行。

setTimeout(function,time_in_mills);

在这里第一个参数应该是一个函数类型,例如,如果你想在3秒后打印出你的名字,你的代码应该是下面的东西。

setTimeout(function(){console.log('your name')},3000);

要记住的关键点是,使用 setTimeout 方法想做什么,在函数内执行。如果要通过parcing调用其他方法一些参数,你的代码应该如下所示,

setTimeout(function(){yourOtherMethod(parameter);},3000);

happy nodejs编码:)

答案 4 :(得分:5)

setTimeout(callback,t)用于在至少t毫秒后运行回调 。实际延迟取决于许多外部因素,如OS计时器粒度和系统负载。

因此,有可能在设定的时间之后稍微调用它,但之前永远不会被调用。

  

计时器不能超过24.8天。