首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Node.js:同步调用相同延迟的setTimeout回调?

Node.js:同步调用相同延迟的setTimeout回调?
EN

Stack Overflow用户
提问于 2018-04-13 20:04:43
回答 2查看 265关注 0票数 4

我有以下代码来演示这个问题:

代码语言:javascript
复制
let count = 5;
while (count--) {
    setTimeout(() => {
        console.log('timeout');
        process.nextTick(() => {
            console.log('tick');
        });
    }, 0);
}

const largeNumber = 20000;
for (let i = 0; i < largeNumber; i += 1) {
    for (let j = 0; j < largeNumber; j += 1) {
        // do nothing here, just be sure all the setTimeout callbacks are in the queue when exiting sync code
    }
}

我期望的输出如下所示:

代码语言:javascript
复制
timeout
tick
timeout
tick
timeout
tick
timeout
tick

因为事件循环检查timeouts队列,所以它创建第一个setTimeout回调,运行它,然后检查nextTick队列。对于进一步的setTimeout回调,它也应该做同样的事情。

但我得到了以下输出:

代码语言:javascript
复制
timeout
timeout
timeout
timeout
timeout
tick
tick
tick
tick
tick

为什么?

EN

回答 2

Stack Overflow用户

发布于 2018-04-13 20:09:21

setTimeoutnextTick将各自将一个函数放在一个函数队列中,以便稍后调用。

当JavaScript事件循环不忙于做其他事情时,它会查看函数队列,看看是否有要运行的函数。

当第一个超时函数运行时,它使用nextTick将一个函数放在队列的末尾(由于要尽快运行)。

但是,队列中的下一个函数是setTimeout放在队列中的下一个函数,并且它已经到期了,所以它首先运行(依此类推)。

票数 2
EN

Stack Overflow用户

发布于 2019-03-10 14:38:31

这要归功于

对于timerscheck阶段,对于多个中间件和计时器,在C到JavaScript之间只有一个转换。这种重复数据删除是一种优化形式,可能会产生一些意想不到的副作用。

您的代码表现出由重复数据删除优化引起的“意想不到的副作用”。

实际上,文档中的示例与您的示例代码非常相似。他们使用的是setImmediate而不是setTimeout,但概念是相同的:

当在check阶段有多个定时器事件在等待时,Node会在处理nextTickQueue之前处理所有的定时器事件。

因此,因为所有setTimeout调用都使用0超时,所以所有回调都会同时进入队列,并且由于重复数据消除优化,Node会对所有回调进行,这会导致'timeout'打印5次。一旦运行了所有的setTimeout回调函数,Node就会处理nextTickQueue,这会导致运行所有5个process.nextTick回调函数,从而导致'tick'打印5次。

请注意,如果您引入一个微型变量delay,以便在同一check阶段期间计时器事件不会在队列中结束,您将避免重复数据消除优化,并将获得预期的输出:

代码语言:javascript
复制
let count = 5;
let delay = 0;
while (count--) {
  setTimeout(() => {
    console.log('timeout');
    process.nextTick(() => {
      console.log('tick');
    });
  }, delay += 1);  // use a tiny variable delay
}

const largeNumber = 20000;
for (let i = 0; i < largeNumber; i += 1) {
  for (let j = 0; j < largeNumber; j += 1) {
    // do nothing here, just be sure all the setTimeout callbacks are in the queue when exiting sync code
  }
}

输出:

代码语言:javascript
复制
timeout
tick
timeout
tick
timeout
tick
timeout
tick
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49816596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档