在面試過程中,基本面試官都會問你一些promise的問題,promise是es6的新內容,主要是用來優化非同步的問題。筆試中經常會讓你寫一些promise和setTimeout的執行結果,這你就必須知道宏任務和微任務的概念了!
如果你經歷過以前的jquery開發專案,你會遇到以下問題:回撥地獄
$.ajax({
...
success: function() {
...
$.ajax({
...
success: function() {
}
})
...
}
})
ajax請求巢狀,原因是我第二個請求依賴的引數在第一個請求的結果中,所以就得這麼一直巢狀下去,ajax是非同步的,不能再外面拿到裡面的結果。這種程式碼導致的問題就是偵錯困難,耦合性非常高,後期改動一個地方就頭疼!維護非常困難,程式碼可讀性差。
於是乎就引入了promise對ajax進行了優化,axios就是基於promise的一個請求封裝庫,他們底層都是基於js原生的XMLHTTPREQUEST.
promise().then().catch()鏈式呼叫,多個請求可以promise().then().then()。
當js主程式執行時,先執行主程式上的同步程式碼,遇到setTimeout或setInterval就把它放入宏佇列中,遇到promise的回撥就把它放到微佇列中,程式執行先執行主程式程式碼,再執行nextTick程式碼,然後微任務,最後宏任務,任務佇列中的依次排隊執行,async和await是配套使用的,await後面接一個promise物件,來看看下面這段程式碼:
setTimeout(function(){console.log(1)},0); // 進入宏任務佇列,最後執行宏任務
new Promise(function(resolve,reject){
console.log(2); //這句程式碼在promise構造器,同步執行
resolve(); // 執行了resolve再把任務放入微佇列
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6); // 主程式程式碼
// 輸出2,6,5,3,4,1
// 下面這個進階程式碼
setTimeout(function(){console.log(1)},0); // 進入宏任務排序為1
new Promise(function(resolve,reject){
console.log(2);
// promise中執行完resolve()才會執行then(),而這裡的resolve在宏任務裡,執行完主程式程式碼後,還得先執行先進入宏佇列中的程式
setTimeout(function(){resolve()},0) // 進入宏任務排序為2
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6);
// 輸出的是 2 6 5 1 3 4
程式碼如下(範例):
async function async1() {
console.log(1);
await async2();
console.log(2); //這裡要等await執行成功才會執行,進入微任務,排序1
}
async function async2() {
console.log(3);
}
console.log(4); //主程式程式碼
setTimeout(function() {
console.log(5);
}, 0) //進入宏任務,最後執行
async1();
new Promise(function(resolve) {
console.log(6); // 這句同步執行
resolve();
}).then(function() {
console.log(7); //進入微任務,排序2
});
console.log(8); // 主程式程式碼
// 輸出的是 4,1,3,6,8,2,7,5
js是單執行緒語言,它的用途決定了他的特性,非同步操作通過事件迴圈機制,先執行同步程式碼,然後微任務,最後宏任務,兩個任務佇列裡的任務排隊依次執行。await後面的程式碼必須等待promise返回結果再執行下面程式碼,await和async是generator函數的語法糖。