【问题标题】:setTimeOut() and setInterval() in Node [duplicate]节点中的 setTimeOut() 和 setInterval() [重复]
【发布时间】:2017-03-31 06:51:46
【问题描述】:

如果我在 10 秒后调用 setTimeOut(),然后执行一组长时间运行的命令,Node.js/JavaScript 是否会等到这些命令完成执行 setTimeOut 中设置的函数? setInterval() 也一样吗?

如果我在代码中同时使用 setTimeOut() 和 setInterval() ,而任务最终可能在同一时间执行,有什么需要注意的吗?

我正在使用 node-cron (https://github.com/kelektiv/node-cron/blob/master/lib/cron.js) 库,我看到它使用了 setTimeOut。我正在尝试使用 setInterval() 添加一些任务。

【问题讨论】:

  • 只是想强调 javascript 代码在单线程中执行的事实。你的担心真的很模糊,所以我真的不能说别的。
  • @tcooc 是单线程并不意味着“Node.js/JavaScript 是否等待这些命令完成执行”的答案是“是”
  • @Alejandro,谢谢,但我在那个问题中没有看到任何对 setInterval() 的引用。
  • @user994165 两者的功能基本相同。想象setInterval 是一个setTimeout,它在被调用时调用setTimeout。我投票结束这个问题,因为不清楚你在问什么。

标签: javascript node.js


【解决方案1】:

node.js 中的定时器事件不能保证在准确的时间被调用。

如果我在 10 秒后调用 setTimeOut(),然后执行 一组长时间运行的命令,Node.js/JavaScript 会等到那些 命令执行完setTimeOut中设置的函数?

是的,它会等到当前在 node.js 中执行的代码完成后,才能为下一个计时器事件提供服务。

setInterval() 也一样吗?

是的,setInterval() 的机制相同。

这里有一些关于 node.js 系统如何工作的解释。

node.js 是一个单线程事件驱动系统(技术上线程在 node.js 内部使用,但它只运行一个 JS 代码的单线程)。

当您使用setTimeout()setInterval() 时,node.js 内部的一些内部机制使用系统计时器来了解下一个计时器应该何时触发。在那一刻,一个事件被插入到 node.js 事件队列中。如果此时 node.js 什么都不做,则立即触发该事件并立即调用相应的回调函数。

但是,如果node.js正忙于运行代码,并且如果事件队列中有其他事件在timer事件之前,则不会立即触发timer事件。

相反,node.js 将一直等到 node.js 中的当前执行线程完成,然后,只有这样,事件队列中的下一个事件才会被拉出,并且该事件的适当回调将被调用.

因此,如果您有一些长时间运行的 node.js 代码,它将阻止所有其他事件(包括计时器事件),直到它完成并且 node.js 可以重新将下一个事件从事件队列中拉出.

【讨论】:

  • @zerkms - 你没有看到我的回答中紧跟在“node.js 是一个单线程事件驱动系统”之后的词,它说“(技术上线程是在 node.js 内部使用的)。 js,但它只运行你的 JS 代码的一个线程)"?
  • 我确实没有。我没有很好的解释我怎么没看到它o_O
  • @zerkms - 它是作为编辑添加的,但在发布后不久添加到您的评论之前。所以,也许您正在查看编辑之前的版本。
【解决方案2】:

答案是:也许,但很可能不是。

当事情是异步的时,不一定能保证什么时候会被调用。当异步事物被调用时,它会被添加到一个内部队列并处理队列。很可能,他们会完成,但这不是你应该依赖的。

相反,您应该做的是触发一些东西来明确表明它已经完成。有很多方法可以解决它,例如回调和Promises。您甚至可以设置一个布尔值来指示状态并在依赖步骤之前检查它。

let aDone = false;

setTimeout(() => { aDone = true; }, 1000);

const startInterval = () => {
    if (!aDone) {
        setTimeout(startInterval, 200); // try again in 200ms
    }

    setInterval(() => { /* do something */ }, 1000);
};

startInterval(); // kick off the interval check

【讨论】:

  • “但这不是你应该依赖的东西”——这到底是什么意思?它会完成吗?
  • @zerkms 这意味着您无法确定它是否会完成,因此如果您需要确定性,请使用其他机制。
  • @zerkms 基本上,你不能相信它。 10 个测试中有 9 个可能有效,但 1 个无效。这是一个竞赛条件。 (编辑删除推荐查看 Wiki,没有注意到 zerkms != OP)
  • @AlejandroC。 “这意味着您无法确定它是否会完成” --- 使用 nodejs,您可以确定它会完成。除非你明确要求事件循环终止。
  • @zerkms 我明白了,你是说事件循环不会提前终止;但是,不能保证通过队列取得进展。这就是我失去问题的背景所得到的。 :-)
猜你喜欢
  • 2011-02-11
  • 2021-10-02
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多