《promise,setTimeout,async,await执行顺序》

338 阅读2分钟

遇到setTimeout,扔到下一轮的宏任务队列里。会等当前这轮Eventloop完成,再去第二轮执行。

遇到new Promise,里边的异步操作是马上执行的,但是then里的回调函数,被扔到微任务队列里。注意,必须是then前边的promise实例里边的异步操作全部完成了,then里边的回调才会在当下被放进微任务队列里。即,在promise实例里,如果执行了resolve(),它只表示要执行then里的第一个函数,它只会指定,不会把then里的回调放进队列。那什么时候放呢?promise实例全都执行完了,得到了,接着执行then的时候,才会把then里的回调放进微任务队列里。

在async函数里,遇到await,先去执行await接着的函数,执行完以后,await会让出线程,把await后边,还是async内部的语句放进微任务队列里。

让本轮所有同步代码执行完毕,会去微任务队列里,依次取出,执行。等微任务队列里的全都执行完了,这轮就完成了。

然后在下一轮的宏任务队列里找,依次执行。

例1:

async function async1() {
    console.log("async1 start");
    await async2();
    console.log("async1 end");
    return 'async return';
}

async function async2() {
    console.log("async2");
}

console.log("script start");

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

async1().then(function (message) { console.log(message) });

new Promise(function(resolve) {
    console.log("promise1");
    resolve();
}).then(function() {
    console.log("promise2");
});

console.log("script end");

比如,async1().then 这里,去执行async1函数,在里边遇到await,所以后边的两行代码会被放进微任务队列里,所以async1函数还没执行完。所以then里边的回调不会现在被放进微任务队列。而是等async1里的全部代码执行完,才会被放进微任务队列里。

分析过程:

"script start"
console.log("setTimeout");-下一轮宏任务
"async1 start"
"async2"

console.log("async1 end"); -微任务1
return 'async return';     -微任务2

"promise1"
console.log("promise2");   -微任务3
"script end"

"async1 end"  1完成

function (message) { console.log(message) }  -微任务4

"promise2"    3完成

'async return'   4完成
"setTimeout"

所以最终顺序:

"script start"
"async1 start"
"async2"
"promise1"
"script end"
"async1 end"
"promise2"
"async return"
"setTimeout"

例2:

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('setTimeout1'); 
}, 200);
 
setTimeout(function() {
    console.log('setTimeout2'); 
    new Promise(function(resolve) { 
        resolve(); 
    }).then(function() { 
        console.log('then1') 
    })
 
    new Promise(function(resolve) { 
        console.log('Promise1'); 
        resolve(); 
    }).then(function() { 
        console.log('then2') 
    }) 
},0)
 
async1();
 
new Promise(function(resolve) { 
    console.log('promise2'); 
    resolve(); 
  }).then(function() { 
    console.log('then3'); 
  });
 
console.log('script end');

分析:

'script start'
200 setTimeout-宏任务队列
0 setTimeout-宏任务

'async1 start'
'async2'

await让出线程,console.log('async1 end'); -微任务队列

'promise2'

function() { 
    console.log('then3'); 
}             -微任务队列

'script end'

取出微任务:
'async1 end'
'then3'

下一轮宏任务:0ms先执行
'setTimeout2'
console.log('then1') -微任务队列
'Promise1'
console.log('then2') -微任务队列
'then1'
'then2'
200ms 执行
'setTimeout1'

最终顺序:

"script start"
"async1 start"
"async2"
"promise2"
"script end"
"async1 end"
"then3"
"setTimeout2"
"Promise1"
"then1"
"then2"
"setTimeout1"