promise與setTimeout的執行順序問題

有一次在面試題中有作到promise與setTimeout的執行順序,當時有點懵,執行順序仍是弄錯了一點點,這裏記錄下

1.輸出

setTimeout(function() {
    console.log(111)
}, 0);
setTimeout(function() {
    console.log(333)
}, 1000);
new Promise(function(resolve){
    console.log(444);
    resolve();
    console.log(555);
}).then(function(){
    console.log(666);
});
console.log(777);
async function test1() {
    console.log("test1");
    await test2();
    console.log("test1 last");
}
async function test2() {
    console.log("test2");
}
test1();
  • 輸出結果
clipboard.png

2.我的理解

  • 首先執行同步代碼,而後以事件輪詢的方式執行異步代碼
  • promise中的異步體如今.then()和.catch()中
  • 而promise中的function裏的是同步代碼
  • 上面的代碼是先執行promise裏的同步代碼,而後執行腳本里自己的同步代碼
  • async不管方法是同步仍是異步均可以用async關鍵字來進行標識
  • 由於用async標識只是顯示代表在該方法內,可能會用到await關鍵字使其變爲異步方法,並且將該異步方法進行了明確的劃分,只有用了await關鍵字時纔是異步操做,其他一併爲同步操做
  • 同 Generator 函數同樣,async 函數返回一個 Promise 對象,可使用 then 方法添加回調函數
  • 當函數執行的時候,一旦遇到 await 就會先返回,等到觸發的異步操做完成,再接着執行函數體內後面的語句
  • await 命令後面的 Promise 對象,運行結果多是 rejected,因此最好把 await 命令放在 try...catch 代碼塊中

3.其餘

  • 在網上還找到了一些資料
參考了這篇文章的一些內容 參考文章
setImmediate(function(){
    console.log(1);
},0);
setTimeout(function(){
    console.log(2);
},0);
new Promise(function(resolve){
    console.log(3);
    resolve();
    console.log(4);
}).then(function(){
    console.log(5);
});
console.log(6);
process.nextTick(function(){
    console.log(7);
});
console.log(8);
  • 輸出結果: 3 4 6 8 7 5 2 1
macro-task: script (總體代碼),setTimeout, setInterval, setImmediate, I/O, UI rendering. 
micro-task: process.nextTick, Promise(原生),Object.observe,MutationObserver
  • 第一步. script總體代碼被執行,執行過程爲
建立setImmediate macro-task
建立setTimeout macro-task
建立micro-task Promise.then 的回調,並執行script console.log(3); resolve(); console.log(4); 此時輸出3和4,雖然resolve調用了,執行了可是總體代碼還沒執行完,沒法進入Promise.then 流程。
console.log(6)輸出6
process.nextTick 建立micro-task
console.log(8) 輸出8
  • 第一個過程事後,已經輸出了3 4 6 8
  • 第二步. 因爲其餘micro-task 的 優先級高於macro-task。
  • 此時micro-task 中有兩個任務按照優先級process.nextTick 高於 Promise,因此先輸出7,再輸出5
  • 第三步,micro-task 任務列表已經執行完畢,家下來執行macro-task. 因爲setTimeout的優先級高於setIImmediate,因此先輸出2,再輸出1。
優先級: promise.Trick()>promise的回調>setTimeout>setImmediate


正在努力學習中,若對你的學習有幫助,留下你的印記唄(點個贊咯^_^)
相關文章
相關標籤/搜索