百度一道關於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
微任務: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)