重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄, 天天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的能夠加入winter的專欄學習【原文有winter的語音】,若有侵權請聯繫我,郵箱:kaimo313@foxmail.com。
一個JavaScript
引擎會常駐於內存中,它等待着宿主
把JavaScript
代碼或者函數傳遞給它執行。
一、ES3
版本以及以前,JavaScript
自己尚未異步執行代碼的能力,宿主環境
傳遞給 JavaScript
引擎,而後按順序執行,由宿主發起任務。前端
二、ES5
以後,JavaScript
引入了 Promise
,不須要瀏覽器的安排,JavaScript
引擎自己也能夠發起任務。瀏覽器
三、採納JSC
引擎術語,把宿主發起的任務稱爲宏觀任務
,把JavaScript
引擎發起的任務稱爲微觀任務
。異步
JavaScript
引擎等待宿主環境分配宏觀任務,在 Node 術語中,把這個部分稱爲事件循環
。
一、用僞代碼來表示:跑在獨立線程中的循環async
while(TRUE) { r = wait(); execute(r); }
二、整個循環作的事情基本上就是反覆 等待 - 執行
,這裏的執行過程,其實都是一個宏觀任務。能夠大體理解爲:宏觀任務的隊列就至關於時間循環。函數
三、在宏觀任務中,JavaScript
的 Promise
還會產生異步代碼
,JavaScript
必須保證這些異步代碼在一個宏觀任務中完成,所以,每一個宏觀任務中又包含了一個微觀任務隊列:以下圖所示學習
例如:Promise
永遠在隊列尾部添加微觀任務。setTimeout
等宿主 API
,則會添加宏觀任務。spa
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
以後輸出。3d
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
這個例子很好的解釋了微任務優先的原理
。code
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也等兩秒)
看完這篇確實幫我解決了以前困擾個人問題,贊一個。。。明天也要加油鴨。。。。