JavaScript setTimeout的执行顺序

时间:2018-05-26 13:55:16

标签: javascript settimeout

我试图理解setTimeout执行的方式。

在下面的示例中,我希望看到' Inside setTimeout'作为控制台日志中的第二行。

但是,我总是看到' Inside setTimeout'作为控制台日志中的第三行。

这是我在日志中始终如一地看到的:

First
Last
Inside setTimeout

知道为什么会这样吗?

<script>
console.log('First');
// NOTE: 0 milliseconds.
setTimeout(function() {console.log('Inside setTimeout')}, 0);
console.log('Last');
</script>

2 个答案:

答案 0 :(得分:2)

即使超时为0ms,它仍会调度异步调用的函数。 setTimeout的工作方式是:

  • 对输入进行一些验证
  • 将该函数添加到从X时间开始调用的列表
  • 返回

稍后,当指定的时间量过去后,浏览器将对任务进行排队以调用该函数,该函数将在处理前面的任务时由事件循环处理。

从不立即调用该函数。那会很混乱;通过始终异步调用它,它是一致的。 (这也是为什么承诺的thencatch处理程序总是异步调用的原因,即使承诺已经解决了。)

所有血腥细节都是in the specification

答案 1 :(得分:0)

使用示例处理setTimeout(function,delayTime): 可以找到更多详细信息here

function main(){
  console.log('A');
  setTimeout(
    function display(){ console.log('B'); }, 0);
    console.log('C');
}
main();

//  Output
//  A
//  C
//  B
  1. 首先将对main函数的调用推入堆栈(作为帧)。然后浏览器将main函数中的第一个语句推送到堆栈,即console.log('A')。执行此语句,并在完成时弹出该帧。字母A显示在控制台中。
  2. 下一个语句(带回调exec()的setTimeout()和0ms等待时间)被推入调用堆栈并开始执行。 setTimeout函数使用浏览器API来延迟回调到提供的函数。一旦切换到浏览器完成(对于计时器),框架(带有setTimeout)就会弹出。
  3. console.log('C')被推送到堆栈,而计时器在浏览器中运行以回调exec()函数。在这种特殊情况下,由于提供的延迟为0毫秒,一旦浏览器收到回传(理想情况下),回调就会被添加到消息队列中。
  4. 在main函数中执行最后一个语句之后,main()帧将从调用堆栈中弹出,从而使其为空。对于浏览器将任何消息从队列推送到调用堆栈,调用堆栈必须首先为空。这就是为什么即使setTimeout()中提供的延迟是0秒,exec()的回调也必须等到调用堆栈中所有帧的执行完成。
  5. 现在回调exec()被推入调用堆栈并执行。字母C显示在控制台上。这是javascript的事件循环。
  6. 因此setTimeout(function,delayTime)中的delay参数不代表执行该函数之后的精确时间延迟。它代表最短等待时间,之后在某个时间点执行该功能。

    - 从medium

    复制

    PS:Philip Roberts撰写的最佳工作视频example