JavaScript事件队列和setTimeout(...)

时间:2016-01-09 08:39:35

标签: javascript

这段代码发生了什么

var start = new Date();

setTimeout(function() {
    var end = new Date();
    console.log('Time elapsed with func1:',end - start, 'ms');
}, 500);

setTimeout(function() {
    var end = new Date();
    console.log('Time elapsed with func2:',end - start, 'ms');
}, 250);

while (new Date() - start < 1000) {}

日志:

Time elapsed with func2: 1001 ms
Time elapsed with func1: 1017 ms

我原本期望func1首先会被激活,因为它是第一个被添加到事件队列中的事件。然后,由于JS的单线程特性,请等待func1返回,然后执行队列中的下一个事件func2。
那么,发生了什么?

3 个答案:

答案 0 :(得分:4)

在计时器到达指定时间时,没有任何内容添加到事件队列中。

因此,事件的顺序如下:

  1. 您注册func1计时器500毫秒。
  2. 您注册func2计时器250毫秒。
  3. 启动while旋转循环。
  4. 在250ms之后,func2计时器触发(JS引擎内部),并将其回调添加到事件队列中。
  5. 500ms后,func1计时器触发(JS引擎内部)并将其回调添加到事件队列中。
  6. 你的while旋转循环终于完成,JS的当前线程结束。
  7. JS引擎将事件队列中的下一个项目拉出func2回调并执行它。
  8. 当回调完成后,它会从事件队列中取出下一个项目,即func1回调并执行它。
  9. 因此,当func2自旋循环完成,然后执行while回调时,您获得了func1回调执行的输出。

答案 1 :(得分:2)

不,等等。它不会将超时调用添加到事件队列中。它由webapi由浏览器处理,然后当你的超时启动时,它会将你的功能添加到事件队列中。

这是什么:https://www.youtube.com/watch?v=8aGhZQkoFbQ#t=13m (从13:00开始)

答案 2 :(得分:0)

Javascript is single-threaded. Even though there are asynchronous callbacks, they are not con-current.

This means, the code inside(setTimeout(fn, num)) only gets called once the entire code has finished execution. Therefore, if num parameter = 5000. This means, the function setTimeout(...) will run: after the entire code (i.e. not just the code up to the point when setTimeout is called but everything) has finished executing + 5 seconds. Hope this helps.