简体   繁体   English

setTimeout 在 Node.JS 中是如何工作的?

[英]How does setTimeout work in Node.JS?

I guess that once it's executed it's on the queue, but in the queue is there any assurance it will invoke exactly after X milliseconds?我想一旦它执行它就在队列中,但是在队列中是否有任何保证它将在 X 毫秒后准确调用? Or will other heavy tasks higher on the queue delay it?或者队列中其他更重的任务会延迟它吗?

The semantics of setTimeout are roughly the same as in a web browser: the timeout arg is a minimum number of ms to wait before executing, not a guarantee. setTimeout 的语义与 web 浏览器中的语义大致相同:超时参数是执行前等待的最小毫秒数,不是保证。 Furthermore, passing 0, a non-number, or a negative number, will cause it to wait a minimum number of ms.此外,传递 0、非数字或负数将导致它等待最小毫秒数。 In Node, this is 1ms, but in browsers it can be as much as 50ms.在 Node 中,这是 1 毫秒,但在浏览器中可能高达 50 毫秒。

The reason for this is that there is no preemption of JavaScript by JavaScript.原因是JavaScript没有抢占JavaScript。 Consider this example:考虑这个例子:

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

The flow here is:这里的流程是:

  1. schedule the timeout for 100ms.将超时时间安排为 100 毫秒。
  2. busywait for 5000ms.忙等待 5000 毫秒。
  3. return to the event loop.返回事件循环。 check for pending timers and execute.检查挂起的计时器并执行。

If this was not the case, then you could have one bit of JavaScript "interrupt" another.如果不是这种情况,那么您可以让一位 JavaScript “中断”另一位。 We'd have to set up mutexes and semaphors and such, to prevent code like this from being extremely hard to reason about:我们必须设置互斥锁和信号量等,以防止这样的代码非常难以推理:

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

The single-threadedness of Node's JavaScript execution makes it much simpler to work with than most other styles of concurrency. Node 的 JavaScript 执行的单线程性使其比大多数其他 styles 并发操作更简单。 Of course, the trade-off is that it's possible for a badly-behaved part of the program to block the whole thing with an infinite loop.当然,权衡是程序的一个行为不端的部分可能会用无限循环阻塞整个事情。

Is this a better demon to battle than the complexity of preemption?这比抢占的复杂性更适合战斗吗? That depends.那要看。

The idea of non-blocking is that the loop iterations are quick.非阻塞的想法是循环迭代很快。 So to iterate for each tick should take short enough a time that the setTimeout will be accurate to within reasonable precision (off by maybe <100 ms or so).因此,为每个滴答进行迭代应该花费足够短的时间,以使 setTimeout 在合理的精度范围内准确(关闭可能 <100 毫秒左右)。

In theory though you're right.虽然理论上你是对的。 If I write an application and block the tick, then setTimeouts will be delayed.如果我编写一个应用程序并阻止滴答声,那么 setTimeouts 将被延迟。 So to answer you're question, who can assure setTimeouts execute on time?所以要回答你的问题,谁能保证 setTimeouts 准时执行? You, by writing non-blocking code, can control the degree of accuracy up to almost any reasonable degree of accuracy.通过编写非阻塞代码,您可以将准确度控制到几乎任何合理的准确度。

As long as javascript is "single-threaded" in terms of code execution (excluding web-workers and the like), that will always happen.只要 javascript 在代码执行方面是“单线程”的(不包括 web-worker 等),这种情况总会发生。 The single-threaded nature is a huge simplification in most cases, but requires the non-blocking idiom to be successful.在大多数情况下,单线程性质是一个巨大的简化,但需要非阻塞习语才能成功。

Try this code out either in your browser or in node, and you'll see that there is no guarantee of accuracy, on the contrary, the setTimeout will be very late:在浏览器或节点中尝试此代码,您会发现无法保证准确性,相反,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){}

Unless the interpreter optimises the loop away (which it doesn't on chrome), you'll get something in the thousands.除非解释器优化循环(它不在 chrome 上),否则你会得到成千上万的东西。 Remove the loop and you'll see it's 500 on the nose...去掉环,你会看到鼻子上有 500...

The only way to ensure code is executed is to place your setTimeout logic in a different process.确保代码执行的唯一方法是将 setTimeout 逻辑放在不同的进程中。

Use the child process module to spawn a new node.js program that does your logic and pass data to that process through some kind of a stream (maybe tcp).使用子进程模块生成一个新的 node.js 程序,该程序执行您的逻辑并通过某种 stream(可能是 tcp)将数据传递给该进程。

This way even if some long blocking code is running in your main process your child process has already started itself and placed a setTimeout in a new process and a new thread and will thus run when you expect it to.这样,即使在您的主进程中运行了一些长阻塞代码,您的子进程已经自己启动并在新进程和新线程中放置了一个 setTimeout,因此将在您期望的时候运行。

Further complication are at a hardware level where you have more threads running then processes and thus context switching will cause (very minor) delays from your expected timing.更复杂的情况是在硬件级别上,您运行的线程多于进程,因此上下文切换将导致(非常小的)您预期的时间延迟。 This should be neglible and if it matters you need to seriously consider what your trying to do, why you need such accuracy and what kind of real time alternative hardware is available to do the job instead.这应该可以忽略不计,如果重要的话,您需要认真考虑您要做什么,为什么需要这样的准确性以及可以使用什么样的实时替代硬件来完成这项工作。

In general using child processes and running multiple node applications as separate processes together with a load balancer or shared data storage (like redis) is important for scaling your code.通常,使用子进程并将多个节点应用程序作为单独的进程与负载均衡器或共享数据存储(如 redis)一起运行对于扩展代码很重要。

setTimeout is a kind of Thread , it holds a operation for a given time and execute. setTimeout是一种Thread ,它持有给定时间的操作并执行。

setTimeout(function,time_in_mills);

in here first argument should be a function type,As aexample if you want to print you name after 3 seconds,you code should be something llike below.在这里第一个参数应该是 function 类型,例如,如果你想在 3 秒后打印你的名字,你的代码应该如下所示。

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

key poitn to remember is, what ever you want to do by using setTimeout method, do it inside a function .if you want to call some other method by parcing some parameters, your code should be looks like below,要记住的关键点是,无论您想使用setTimeout方法做什么,都可以在 function 中执行。如果您想通过分配一些参数来调用其他方法,您的代码应如下所示,

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

happy nodejs coding:)快乐的nodejs编码:)

setTimeout(callback,t) is used to run callback after at least t millisecond . setTimeout(callback,t)用于在至少 t 毫秒后运行回调。 The actual delay depends on many external factors like OS timer granularity and system load.实际延迟取决于许多外部因素,例如 OS 计时器粒度和系统负载。

So, there is a possibility that it will be called slightly after the set time, but will never be called before.因此,它有可能会在设置的时间之后被调用,但之前永远不会被调用。

A timer can't span more than 24.8 days.计时器不能超过 24.8 天。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM