摘要:全部代碼是一個先執(zhí)行一個執(zhí)行過程中遇到等異步操作則創(chuàng)建一個遇到等創(chuàng)建一個這兩個分別被掛起執(zhí)行棧為空時開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調用棧注每一次事件循環(huán),只處理一個。
JS異步原理(事件,隊列) 調用棧
JS執(zhí)行時會形成調用棧,調用一個函數(shù)時,返回地址、參數(shù)、本地變量都會被推入棧中,如果當前正在運行的函數(shù)中調用另外一個函數(shù),則該函數(shù)相關內容也會被推入棧頂.該函數(shù)執(zhí)行完畢,則會被彈出調用棧.變量也隨之彈出,由于復雜類型值存放于堆中,因此彈出的只是指針,他們的值依然在堆中,由GC決定回收.
尾調用:指某個函數(shù)的最后一步是調用另一個函數(shù)。由調用棧可知,調用棧中有a函數(shù),如果a函數(shù)調用b函數(shù),則b函數(shù)也隨之入棧,此時棧中就會有兩個函數(shù).但是如果b函數(shù)是a函數(shù)最后一步,并且不需保留外層函數(shù)調用記錄,即a函數(shù)調用位置變量等都不需要用到,則該調用棧中會只保留b函數(shù),這就叫做"尾調用優(yōu)化"(Tail call optimization),即只保留內層函數(shù)的調用記錄。如果所有函數(shù)都是尾調用,那么完全可以做到每次執(zhí)行時,調用記錄只有一項,這將大大節(jié)省內存。這就是"尾調用優(yōu)化"的意義。
function a() { let m = 1; let n = 2; return b(m + n); } a(); // 等同于 function a() { return b(3); } a(); // 等同于 b(3);事件循環(huán)(event loop)和任務隊列(task queue)
JS的異步機制由事件循環(huán)和任務隊列構成.JS本身是單線程語言,所謂異步依賴于瀏覽器或者操作系統(tǒng)等完成. JavaScript 主線程擁有一個執(zhí)行棧以及一個任務隊列,主線程會依次執(zhí)行代碼,當遇到函數(shù)時,會先將函數(shù)入棧,函數(shù)運行完畢后再將該函數(shù)出棧,直到所有代碼執(zhí)行完畢。
遇到異步操作(例如:setTimeout, AJAX)時,異步操作會由瀏覽器(OS)執(zhí)行,瀏覽器會在這些任務完成后,將事先定義的回調函數(shù)推入主線程的任務隊列(task queue)中,當主線程的執(zhí)行棧清空之后會讀取task queue中的回調函數(shù),當task queue被讀取完畢之后,主線程接著執(zhí)行,從而進入一個無限的循環(huán),這就是事件循環(huán).
Microtask 與 MacrotaskHowever, we only have one main thread and one call-stack, so in case there is another request being served when the said file is read, its callback will need to wait for the stack to become empty. The limbo where callbacks are waiting for their turn to be executed is called the task queue (or event queue, or message queue). Callbacks are being called in an infinite loop whenever the main thread has finished its previous task, hence the name "event loop".
一個瀏覽器環(huán)境(unit of related similar-origin browsing contexts.)只能有一個事件循環(huán)(Event loop),而一個事件循環(huán)可以多個任務隊列(Task queue),每個任務都有一個任務源(Task source)。例如,客戶端可能實現(xiàn)了一個包含鼠標鍵盤事件的任務隊列,還有其他的任務隊列,而給鼠標鍵盤事件的任務隊列更高優(yōu)先級,例如75%的可能性執(zhí)行它。這樣就能保證流暢的交互性,而且別的任務也能執(zhí)行到了。但是,同一個任務隊列中的任務必須按先進先出的順序執(zhí)行。多個任務隊列,是為了方便控制優(yōu)先級。任務隊列是一個先進先出的隊列.
macrotask 和 microtask 是異步任務的兩種分類。在掛起任務時,JS 引擎會將所有任務按照類別分到這兩個隊列中,首先在 macrotask 的隊列(這個隊列也被叫做 task queue)中取出第一個任務,執(zhí)行完畢后取出 microtask 隊列中的所有任務順序執(zhí)行;之后再取 macrotask 任務,周而復始,直至兩個隊列的任務都取完。
全部代碼(script)是一個macrotask,js先執(zhí)行一個macrotask,執(zhí)行過程中遇到(setTimeout, setInterval, setImmediate等)異步操作則創(chuàng)建一個macrotask,遇到(process.nextTick, Promises等)創(chuàng)建一個microtask,這兩個queue分別被掛起.執(zhí)行棧為空時開始處理macrotask,完成后處理microtask,直到該microtask全部執(zhí)行完,然后繼續(xù)主線程調用棧.
注:每一次事件循環(huán)(one cycle of the event loop),只處理一個 (macro)task。待該 macrotask 完成后,所有的 microtask 會在同一次循環(huán)中處理。處理這些 microtask 時,還可以將更多的 microtask 入隊,它們會一一執(zhí)行,直到整個 microtask 隊列處理完。
兩個類別的具體分類如下:
macro-task: script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task: process.nextTick, Promises(這里指瀏覽器實現(xiàn)的原生 Promise), Object.observe, MutationObserver
參考文章:
Promise的隊列與setTimeout的隊列有何關聯(lián)?
node事件循環(huán)
深入淺出JavaScript事件循環(huán)機制(下)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/112483.html
摘要:全部代碼是一個先執(zhí)行一個執(zhí)行過程中遇到等異步操作則創(chuàng)建一個遇到等創(chuàng)建一個這兩個分別被掛起執(zhí)行棧為空時開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調用棧注每一次事件循環(huán),只處理一個。 JS異步原理(事件,隊列) 調用棧 JS執(zhí)行時會形成調用棧,調用一個函數(shù)時,返回地址、參數(shù)、本地變量都會被推入棧中,如果當前正在運行的函數(shù)中調用另外一個函數(shù),則該函數(shù)相關內容也會被推入棧頂.該函數(shù)執(zhí)...
摘要:全部代碼是一個先執(zhí)行一個執(zhí)行過程中遇到等異步操作則創(chuàng)建一個遇到等創(chuàng)建一個這兩個分別被掛起執(zhí)行棧為空時開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調用棧注每一次事件循環(huán),只處理一個。 JS異步原理(事件,隊列) 調用棧 JS執(zhí)行時會形成調用棧,調用一個函數(shù)時,返回地址、參數(shù)、本地變量都會被推入棧中,如果當前正在運行的函數(shù)中調用另外一個函數(shù),則該函數(shù)相關內容也會被推入棧頂.該函數(shù)執(zhí)...
摘要:我們可以為元素添加屬性然后在回調函數(shù)中接受該元素在樹中的句柄,該值會作為回調函數(shù)的第一個參數(shù)返回。使用最常見的用法就是傳入一個對象。單向數(shù)據(jù)流,比較有序,有便于管理,它隨著視圖庫的開發(fā)而被概念化。 面試中問框架,經常會問到一些原理性的東西,明明一直在用,也知道怎么用, 但面試時卻答不上來,也是挺尷尬的,就干脆把react相關的問題查了下資料,再按自己的理解整理了下這些答案。 reac...
摘要:道阻且長啊前端面試總結前端面試筆試面試騰訊一面瀏覽器工作原理瀏覽器的主要組件包括用戶界面包括地址欄后退前進按鈕書簽目錄瀏覽器引擎用來查詢及操作渲染引擎的接口渲染引擎渲染界面和是基于兩種渲染引擎構建的,使用自主研發(fā)的渲染引擎,和都使用網絡用來 道阻且長啊TAT(前端面試總結) 前端 面試 筆試 面試 騰訊一面 1.瀏覽器工作原理 瀏覽器的主要組件包括: 用戶界面- 包括地址欄、后退/前...
閱讀 881·2023-04-25 19:17
閱讀 2179·2021-09-10 11:26
閱讀 1898·2019-08-30 15:54
閱讀 3411·2019-08-30 15:53
閱讀 2681·2019-08-30 11:20
閱讀 3391·2019-08-29 15:12
閱讀 1230·2019-08-29 13:16
閱讀 2384·2019-08-26 12:19