問題助琐!
- JS 為什么是單線程的?
- 為什么需要異步?
- 單線程又是如何實現(xiàn)異步的呢?
- promise 的優(yōu)點是什么宋距?
- 如何手動實現(xiàn)一個 Promise沥匈?
- async 做一件什么事情碟狞?
- await 在等什么律罢?
- await 等到之后耕姊,做了一件什么事情桶唐?
- async/await 比 promise 有哪些優(yōu)勢?
js 是單線程的
js 是單線程的茉兰,所謂單線程尤泽,是指在 JS 引擎中負責解釋和執(zhí)行 JavaScript 代碼的線程只有一個, 有且只有一個調(diào)用棧,每次只能做一件事规脸, 同一時間只能做一件事坯约,瀏覽器渲染和 js 共用一個線程,不妨叫它主線程莫鸭。之所以設(shè)計成這樣是為了避免 dom 渲染的沖突闹丐。
但是實際上還存在其他的線程。例如:處理 AJAX 請求的線程被因、處理 DOM 事件的線程妇智、定時器線程、讀寫文件的線程(例如在 Node.js 中)等等氏身。這些線程可能存在于 JS 引擎之內(nèi)巍棱,也可能存在于 JS 引擎之外,在此我們不做區(qū)分蛋欣。不妨叫它們工作線程航徙。
但是 js 是需要異步操作的,比如 ajax 請求
通過 event loop 實現(xiàn)異步
為了支持異步操作陷虎,通過 event loop(事件循環(huán)到踏,事件輪詢)這種機制來實現(xiàn)異步
瀏覽器的 Event Loop 遵循的是 HTML5 標準,而 NodeJs 的 Event Loop 遵循的是 libuv尚猿。
任務(wù)隊列
Js 中窝稿,有兩類任務(wù)隊列:宏任務(wù)隊列(macro tasks)和微任務(wù)隊列(micro tasks)。宏任務(wù)隊列可以有多個凿掂,微任務(wù)隊列只有一個伴榔。那么什么任務(wù)纹蝴,會分到哪個隊列呢?
宏任務(wù):script(全局任務(wù)), setTimeout, setInterval, setImmediate, I/O, UI rendering.
微任務(wù):process.nextTick, Promise, Object.observer, MutationObserver.
瀏覽器的執(zhí)行流程
當 call stack 空的時候踪少,就會從任務(wù)隊列中塘安,取任務(wù)來執(zhí)行。瀏覽器這邊援奢,共分 3 步:
取一個宏任務(wù)來執(zhí)行兼犯。執(zhí)行完畢后,下一步集漾。
取一個微任務(wù)來執(zhí)行切黔,執(zhí)行完畢后,再取一個微任務(wù)來執(zhí)行具篇。直到微任務(wù)隊列為空绕娘,執(zhí)行下一步。
更新 UI 渲染栽连。
Event Loop 會無限循環(huán)執(zhí)行上面 3 步险领,這就是 Event Loop 的主要控制邏輯。其中秒紧,第 3 步(更新 UI 渲染)會根據(jù)瀏覽器的邏輯绢陌,決定要不要馬上執(zhí)行更新。畢竟更新 UI 成本大熔恢,所以脐湾,一般都會比較長的時間間隔,執(zhí)行一次更新叙淌。
測試
這是一道去年「今日頭條」的面試題秤掌,試著看一下它的執(zhí)行流程
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function() {
console.log("setTimeout");
}, 0);
async1();
new Promise(function(resolve) {
console.log("promise1");
resolve();
}).then(function() {
console.log("promise2");
});
console.log("script end");
(未完待續(xù)...)