1. 程式人生 > >百度一道關於promise筆試題的總結

百度一道關於promise筆試題的總結

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

Promise.resolve(function () {
  console.log(2);
})

new Promise(function (resolve) {
  console.log(3);
});

console.log(4);
輸出:3 4 undefined 1

js中的事件執行主要分為兩個任務型別 macro task以及micro task 也就是巨集仁務和微任務

巨集仁務:script(全域性任務),setTimeout ,setInterval ,setImmediate ,I/O

,UI rendering
微任務:process.nextTick,promise,Object.observer,MutationObserver

執行順序為script先進入函式呼叫棧,然後執行遇到任何其他巨集仁務,比如遇到了setTimeout,就把setTimeout放進巨集仁務佇列中,遇到了微任務就放入微任務佇列中,等到函式呼叫棧的所有內容出棧後,然後執行微任務佇列,然後再回頭執行巨集仁務佇列,再進入函式呼叫棧再執行微任務佇列,直到巨集仁務佇列執行完畢。

//遇到setTimeout,放入巨集仁務佇列
setTimeout(function () {
  console.log(1
); }, 0); //遇到promise,放入微任務佇列 Promise.resolve(function () { console.log(2); }) //這裡雖然遇到了promise,但是是用new宣告的,也就是立即執行,所以會先輸出3 new Promise(function (resolve) { console.log(3); }); //第二輸出4 console.log(4); //需要注意的是那個undefined並不是微任務輸出的,而是console.log(4)輸出的,具體可以控制檯測試 ----然後執行微任務,這個微任務並沒有呼叫,所以也不會執行,然後執行巨集仁務佇列中的setTimeout,輸出1

注意以下幾點:
1.需要注意的是那個undefined並不是微任務輸出的,而是console.log(4)輸出的
2.

Promise.resolve(function () {
  console.log(2);
})

該任務並沒有呼叫,所以也不會執行
3.Promise.resolve(function(){console.log(2);}),這種寫法在擴充套件的finally()方法中也有用到,不屬於寫法錯誤吧?請問具體怎麼處理這個函式的?

這種寫法也不算錯,只能說是定義沒呼叫,Promise.resolve(function(){console.log(2);}).then(function(cb){cb()})
Promise.resolve(value)裡的引數value是在then(function(value){})裡面取得
4.

new Promise(function (resolve) {
  console.log(3);
});

這裡雖然遇到了promise,但是是用new宣告的,也就是立即執行,所以會先輸出3
promise建構函式傳入的函式會在本次new 操作立刻執行
5.非同步的原理

JavaScript是單執行緒執行的,無法同時執行多段程式碼。當某一段程式碼正在執行的時候,所有後續的任務都必須等待,形成一個佇列。一旦當前任務執行完畢,再從佇列中取出下一個任務,這也常被稱為
“阻塞式執行”。所以一次滑鼠點選,或是計時器到達時間點,或是Ajax請求完成觸發了回撥函式,這些事件處理程式或回撥函式都不會立即執行,而是立即排隊,一旦執行緒有空閒就執行。假如當前
JavaScript執行緒正在執行一段很耗時的程式碼,此時發生了一次滑鼠點選,那麼事件處理程式就被阻塞,使用者也無法立即看到反饋,事件處理程式會被放入任務佇列,直到前面的程式碼結束以後才會開始執行。如果程式碼中設定了一個
setTimeout,那麼瀏覽器便會在合適的時間,將程式碼插入任務佇列,如果這個時間設為
0,就代表立即插入佇列,但不是立即執行,仍然要等待前面程式碼執行完畢。所以 setTimeout 並不能保證執行的時間,是否及時執行取決於
JavaScript 執行緒是擁擠還是空閒。

所以程式碼會先執行 new Promise(function(resolve){console.log(3);});

然後執行 console.log(4);
這個返回的是undefined
最後執行 setTimeout(function(){console.log(1);},0)