【问题标题】:setTimeout behaviour with blocking code带有阻塞代码的 setTimeout 行为
【发布时间】:2013-02-13 21:00:39
【问题描述】:

这是我的测试代码(小提琴here):

console.log('Before wait');
setTimeout(function () { console.log('Yo!'); }, 1000);
var start = Date.now();
while (Date.now() < start + 3000) {}
console.log('After wait');

这是 Chrome 中事件的时间线:

  • 时间 0 秒:打印“等待前”
  • 时间 3 秒:打印“等待后”,然后在“哟!”之后立即打印

这种行为是否符合规范?为什么没有

  • 时间 0 秒:打印“等待前”
  • 时间 3 秒:打印“等待后”
  • 时间 4 秒:打印“Yo!”

?

【问题讨论】:

    标签: javascript settimeout


    【解决方案1】:

    JavaScript 是单线程的。如果某些代码块使用执行线程,则无法执行其他代码。这意味着您的setTimeout() 调用必须等到主执行(忙等待while 循环的那个)完成。

    这是发生的事情:您安排setTimeout()在一秒钟后执行,然后阻塞主线程3秒钟。这意味着当你的繁忙循环结束时,超时已经晚了 2 秒 - JS 引擎试图通过尽快调用你的超时来跟上 - 即立即。

    其实是这样的:

    while (Date.now() < start + 3000) {}
    

    是 JavaScript 中最糟糕的事情之一。您将 JavaScript 执行线程保持 3 秒,并且无法执行其他事件/回调。通常浏览器会在这段时间内“冻结”。

    【讨论】:

    • JavaScript 是单线程的事实解释了为什么“哟!”打印 after “After wait”,仅此而已。
    • @Randomblue:你是对的,我错过了你的问题。更新了我的答案。
    • @Randomblue,这是最好的答案(到目前为止),尽管赞成票较少。很奇怪。
    • 我认为这也是一个很好的答案——它确实准确地描述了事件的顺序,但没有直接回答为什么“哟!”的问题。在 4 秒而不是 3 或 1 秒后不打印。对我来说,它似乎在打印“哟!” 4 秒后不合逻辑。
    【解决方案2】:

    setTimeout 的延迟是相对于调用它的确切时间点而言的。当您仍在忙于等待时,它就会过期。因此它将在控件返回事件循环的下一个瞬间执行。

    编辑:

    规范在这一点上有点含糊,但我想这是预期的且唯一直接的解释:

    setTimeout(函数,毫秒)

    此方法在经过指定的毫秒数后调用该函数一次,直到通过调用 clearTimeout 取消。这 方法返回一个 timerID,它可以在随后的调用中使用 clearTimeout 取消间隔。

    【讨论】:

    • 你有支持这个的规格吗?
    • 在上面编辑 - 添加了规范的摘录。
    • 在我看来很明显,传递给“setTimeout”的函数将在相对于您调用该函数时尽可能接近指定的毫秒数执行 - 在问题中您似乎会认为它在当前线程退出后 1 秒执行 - 但这对我来说似乎根本不合逻辑。
    【解决方案3】:

    当您在 setTimeout 调用之后运行忙等待循环时,您不会为“哟!”留出时间打印出来,因为 Javascript 运行时正忙于您的循环(实际上,由于循环条件的继续评估,空语句也使其忙)。

    您应该始终避免这种繁忙的等待循环,因为在完成之前,不能在该窗口中调用或运行任何其他内容。

    【讨论】:

    • '等待'总是会赢。
    • 谢谢指正,我会更新答案的。无论如何,我认为其余的可能都是真的。这甚至与 javascript 无关,而是与很多环境有关。
    【解决方案4】:

    不确定它是否可以帮助您,但此问题已在以下内容中进行了解释: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Run-to-completion

    因此,第二个参数表示最短时间,而不是保证时间。

    【讨论】:

      猜你喜欢
      • 2017-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多