promise和setTimeout的执行顺序?谈谈浏览器中的Event Loop

promisesetTimeout都是处理异步回调的,那么到底谁先谁后呢?

我们来看一个例子:

(function test() {
    setTimeout(function() {console.log(1)}, 0);
    new Promise(function executor(resolve) {
        console.log(2);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(3);
    }).then(function() {
        console.log(4);
    });
    console.log(5);
})()

答案是 2 3 5 4 1,而且在控制台编译的时候,看到1和其他的数字不同,函数的返回值都出现了才执行。那么,为什么会这样呢?

promise和setTimeout的执行顺序?谈谈浏览器中的Event Loop

当我们执行JS代码的时候,遇到异步代码时,会被挂起并加入到Task队列中。当执行栈为空的时候,就在Task队列中拿出需要执行的代码。不同的任务会被分配到不同的队列,我们可以把它分为 微任务(microtask) 和 宏任务(macrotask)。

  • 微任务包括 process.nextTickpromise ,MutationObserver
  • 宏任务包括 script , setTimeoutsetIntervalsetImmediate ,I/OUI rendering

浏览器的执行Even Loop执行顺序如下:

  1. 首先执行同步代码,这也属于宏任务。
  2. 执行完同步代码后,查询是否有宏任务中的异步代码需要执行。(这个时候只是查询,并没有执行哦)
  3. 执行完所有的微任务,并完成页面渲染
  4. 开始下一轮EventLoop
  5. 如果 2 步骤中查询到要执行的异步代码,这时候执行。如setTimeout函数

这样,上图的情况就能解释了。

原文地址:https://www.cnblogs.com/zzsdream/p/14130915.html