JS异步--setTimeout及Promise的执行过程

Promise

Promise新建后会立即执行,then方法指定的回调函数在当前脚本的所有同步任务执行完时执行

setTimeout

  setTimeout(function() {
          console.log('B');
     }, 0);

第二个参数设为0只是把函数放入异步队列,浏览器执行完同步队列中的任务才去执行异步队列中的任务,所以A,B处于异步队列中最后才被执行

关于异步任务队列

Macrotasks(task queue)和Microtasks 都属于异步任务中的一种,他们分别有如下API:
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering
microtasks: process.nextTick, Promise, MutationObserver

Promise的函数代码的异步任务会优先setTimeout的延时为0的任务先执行。因为任务队列分为 macrotasks 和 microtasks, 而promise中的then方法的函数会被推入到microtasks队列中,而setTimeout函数会被推入到macrotasks

事件循环的执行过程

开始 -> 取macrotasks的一个任务(task)执行-> 取microtask全部任务依次执行 -> 取macrotasks下一个任务执行 -> 再次取出microtask全部任务执行 -> ... 这样循环往复

注:macrotask的前一个task的回调函数会在下一个task开头执行,即在前一趟的microtask之后执行

setTimeout(() => {
    console.log('A');
}, 0);


var obj = {
func: function() {
     setTimeout(function() {
          console.log('B');
     }, 0);

     return new Promise(function(resolve) {
          console.log('C');
          resolve();
         });
    }
};

obj.func().then(function() {
    console.log('D');
});

console.log('E');
//输出结果如下
//C
//E
//D
//A
//B

1、首先 setTimeout A 被加入到事件队列中 ==> 此时macrotasks中有[‘A’];

2、obj.func()执行时,setTimeout B 被加入到事件队列中 ==> 此时macrotasks中有[‘A’,‘B’];

3、接着return一个Promise对象,Promise 新建后立即执行console.log(‘C’); 控制台首次打印‘C’;

4、然后,then方法指定的回调函数,被加入到microtasks队列,将在当前脚本所有同步任务执行完才会执行。 ==> 此时microtasks中有[‘D’];

5、然后继续执行当前脚本的同步任务,故控制台第二次输出‘E’;

6、此时所有同步任务执行完毕,如上所述先检查microtasks队列完成其中所有任务,故控制台第三次输出‘D’;

7、最后再执行macrotask的任务,并且按照入队列的时间顺序,控制台第四次输出‘A’,控制台第五次输出‘B’。

解释来源:https://www.qdskill.com/javascript/8429.html

你可能感兴趣的:(JS异步--setTimeout及Promise的执行过程)