代码之家  ›  专栏  ›  技术社区  ›  Brandon

为什么setTimeout延迟0仍然在for循环中的所有其他同步代码之后运行?[副本]

  •  3
  • Brandon  · 技术社区  · 7 年前

    我知道已经讨论过这个问题的不同版本,我认为这是独一无二的。为什么延迟为0仍会导致以下行为。

    for(var i = 0; i <3; i ++) {
      console.log(i, 'started');
      setTimeout(()=> {
        console.log(i);
      },0)
      console.log(i, 'done');
    }
    
    console.log('loop over');
    
       // 0 started
       // 0 done
       // 1 started
       // 1 done
       // 2 started
       // 2 done
       // loop over
       // 3 3 3 
    

    这是我想要的 认为 到目前为止,我知道:

    引用MDN关于堆栈上设置超时位置的内容:

    这是因为即使调用setTimeout的延迟为 零,它被放置在队列中,并计划在下一个 机会不是马上。当前执行的代码必须完成 在执行队列上的函数之前,因此 执行顺序可能不符合预期。

    我说的for循环和任何同步代码都放在调用堆栈上,对吗 之前 setTimeout,即使您将延迟设置为0,setTimeout始终只会在for循环完成后运行?否则,为什么延迟0仍然会导致上述行为?

    谢谢

    编辑:

    在正确的方向上开始之后,我找到了一些视频和一个很好的小工具,它向您展示了事件循环以及它与此示例代码的关系。以下是JS运行时模拟器: loupe

    2 回复  |  直到 7 年前
        1
  •  3
  •   john_omalley    7 年前

    JavaScript在浏览器和服务器上都作为事件循环运行。运行时不断轮询事件。事件包括用户操作(例如,单击DOM元素x)、I/O(从I/O或ajax调用返回的数据)和计时器事件(在本例中)。 setTimeout(fn, 0) 只需在0毫秒后添加事件循环要处理的事件即可。它将始终在处理当前事件后执行。

        2
  •  0
  •   gawicks    7 年前

    我说的for循环和任何同步代码的位置正确吗 在setTimeout之前的调用堆栈上

    为了显得迂腐,setTimeout()本身会被同步调用,并放在调用堆栈的后面 console.log(i, 'started'); . 这是设置超时 回调函数 (在你的情况下 console.log(i) )将其排队并异步调用。