重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,天天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的能夠加入winter的專欄學習【原文有winter的語音】,若有侵權請聯繫我,郵箱:kaimo313@foxmail.com。前端
一個
JavaScript
引擎會常駐於內存中,它等待着宿主
把JavaScript
代碼或者函數傳遞給它執行。瀏覽器
一、ES3
版本以及以前,JavaScript
自己尚未異步執行代碼的能力,宿主環境
傳遞給 JavaScript
引擎,而後按順序執行,由宿主發起任務。異步
二、ES5
以後,JavaScript
引入了 Promise
,不須要瀏覽器的安排,JavaScript
引擎自己也能夠發起任務。async
三、採納JSC
引擎術語,把宿主發起的任務稱爲宏觀任務
,把JavaScript
引擎發起的任務稱爲微觀任務
。函數
JavaScript
引擎等待宿主環境分配宏觀任務,在 Node 術語中,把這個部分稱爲事件循環
。學習
一、用僞代碼來表示:跑在獨立線程中的循環ui
while(TRUE) {
r = wait();
execute(r);
}
複製代碼
二、整個循環作的事情基本上就是反覆 等待 - 執行
,這裏的執行過程,其實都是一個宏觀任務。能夠大體理解爲:宏觀任務的隊列就至關於時間循環。spa
三、在宏觀任務中,JavaScript
的 Promise
還會產生異步代碼
,JavaScript
必須保證這些異步代碼在一個宏觀任務中完成,所以,每一個宏觀任務中又包含了一個微觀任務隊列:以下圖所示線程
例如:Promise
永遠在隊列尾部添加微觀任務。setTimeout
等宿主 API
,則會添加宏觀任務。code
JavaScript
語言提供的一種標準化的異步管理
方式,當進行 io、等待或者其它異步操做的函數,不返回真實結果,而返回一個承諾
,函數的調用方能夠在合適的時機,選擇等待這個承諾兌現
。
function sleep(duration) {
return new Promise(function(resolve, reject) {
setTimeout(resolve,duration);
})
}
sleep(1000).then( ()=> console.log("finished"));
複製代碼
Promise
的 then
回調是一個異步
的執行過程。
Promise
函數中的執行順序var r = new Promise(function(resolve, reject){
console.log("a");
resolve()
});
r.then(() => console.log("c"));
console.log("b")
// 輸出順序:a b c
複製代碼
setTimeout
混用的 Promise
var r = new Promise(function(resolve, reject){
console.log("a");
resolve()
});
setTimeout(()=>console.log("d"), 0)
r.then(() => console.log("c"));
console.log("b")
// 輸出順序:a b c d
複製代碼
Promise
產生的是 JavaScript
引擎內部的微任務
,而 setTimeout
是瀏覽器 API
,它產生宏任務
。因此d
一定在 c
以後輸出。
1
秒的 Promise
setTimeout(()=>console.log("d"), 0)
var r = new Promise(function(resolve, reject){
resolve()
});
r.then(() => {
var begin = Date.now();
while(Date.now() - begin < 1000);
console.log("c1")
new Promise(function(resolve, reject){
resolve()
}).then(() => console.log("c2"))
});
// 輸出順序:c1 c2 d
複製代碼
這個例子很好的解釋了微任務優先的原理
。
function sleep(duration) {
return new Promise(function(resolve, reject) {
console.log("b");
setTimeout(resolve,duration);
})
}
console.log("a");
sleep(5000).then(()=>console.log("c"));
// 輸出順序:a b c(c要等5秒)
複製代碼
第一個宏觀任務中,包含了前後同步執行的 console.log("a")
; 和 console.log("b")
;。
setTimeout
後,第二個宏觀任務執行調用了 resolve
,而後 then
中的代碼異步獲得執行,調用了 console.log("c")
。
async/await
是ES2016
新加入的特性,它提供了用for、if
等代碼結構來編寫異步的方式,而且運行時基礎是Promise
。
一、async
函數是在 function
關鍵字以前加上 async
關鍵字,這樣就定義了一個 async
函數,能夠在其中使用 await
來等待一個 Promise
。
function sleep(duration) {
return new Promise(function(resolve, reject) {
setTimeout(resolve,duration);
})
}
async function foo(){
console.log("a")
await sleep(2000)
console.log("b")
}
foo();
// 輸出順序:a b(b要等兩秒)
複製代碼
二、async
嵌套
function sleep(duration) {
return new Promise(function(resolve, reject) {
setTimeout(resolve,duration);
})
}
async function foo(name){
await sleep(2000)
console.log(name)
}
async function foo2(){
await foo("a");
await foo("b");
}
foo2();
// 輸出順序:a(a等兩秒) b(b也等兩秒)
複製代碼
看完這篇確實幫我解決了以前困擾個人問題,贊一個。。。明天也要加油鴨。。。。