setTimeout 、 promise、async await 的执行顺序?宏任务、微任务,分别包含哪些?

JS 分为同步任务和异步任务

同步任务在主线程上执行

异步任务放在主线程之外的一个任务队列

主线程执行完毕后,读取任务队列的内容

 

宏任务(macro)task:当前主线程上执行的就是一个宏任务。例: script 的代码、setTimeout、setInterval、postMessage等。

微任务:microtask。例:Promise.then、await后面的代码。

在执行当前宏任务时(同步执行时),遇到 setTimeout 会把它放到宏任务队列。遇到Promise.then会放到微任务队列。

当前 宏任务 执行完毕后,会先查看微任务队列,如果有任务,优先执行,否则执行下一个宏任务。所以 promise.then 会先于 setTimeout执行。

 

试试这段代码(头条):

//请写出输出内容
async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
	console.log('async2');
}

console.log('script start');

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

async1();

new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');


//打印结果
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/

 

根据上面的原则来,基本没啥问题了。但是肯定有个疑惑的地方。为什么 “async1 end” 跑到了倒数第三个。

那是因为 async 函数中,遇到 await 会跳出当前函数,并让出线程,再将await后面的代码放到 微任务(microtask)队列中

 

整个执行过程:

1、同步执行, 输出“script start”。

2、遇到setTimeout,将里面代码放到宏任务队列。

3、继续往下,输出 “async1 start”,然后执行 async2函数,输出 “async2”。

4、async2执行完毕,将await async2 后面的代码加入到 微任务队列;

5、继续执行,new Promise, 同步输出“promise1”。

6、遇到 promise.then,加入到微任务队列,

7、然后输出 "script end"。

8、当前宏任务执行完毕,查看微任务队列,按照先进先出原则。

9、依次输出“async1 end”、“promise2”

10、执行下一个宏任务,里面只有一个setTimeout,所以最后输出 “setTimeout”

 

同步执行的:[script start] [async1 start] [async2] [promise1] [script end]

微任务队列:[async1 end] [ promise2 ]

宏任务队列:[setTimeout]

posted @ 2020-02-29 17:01  蒋大忙  阅读(1973)  评论(0编辑  收藏  举报