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


正在努力學習中,若對你的學習有幫助,留下你的印記唄(點個贊咯^_^)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章