成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[面試專題]JS異步原理(事件,隊(duì)列)

MageekChiu / 2934人閱讀

摘要:全部代碼是一個(gè)先執(zhí)行一個(gè)執(zhí)行過程中遇到等異步操作則創(chuàng)建一個(gè)遇到等創(chuàng)建一個(gè)這兩個(gè)分別被掛起執(zhí)行棧為空時(shí)開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調(diào)用棧注每一次事件循環(huán),只處理一個(gè)。

JS異步原理(事件,隊(duì)列) 調(diào)用棧

JS執(zhí)行時(shí)會(huì)形成調(diào)用棧,調(diào)用一個(gè)函數(shù)時(shí),返回地址、參數(shù)、本地變量都會(huì)被推入棧中,如果當(dāng)前正在運(yùn)行的函數(shù)中調(diào)用另外一個(gè)函數(shù),則該函數(shù)相關(guān)內(nèi)容也會(huì)被推入棧頂.該函數(shù)執(zhí)行完畢,則會(huì)被彈出調(diào)用棧.變量也隨之彈出,由于復(fù)雜類型值存放于堆中,因此彈出的只是指針,他們的值依然在堆中,由GC決定回收.

尾調(diào)用:指某個(gè)函數(shù)的最后一步是調(diào)用另一個(gè)函數(shù)。由調(diào)用棧可知,調(diào)用棧中有a函數(shù),如果a函數(shù)調(diào)用b函數(shù),則b函數(shù)也隨之入棧,此時(shí)棧中就會(huì)有兩個(gè)函數(shù).但是如果b函數(shù)是a函數(shù)最后一步,并且不需保留外層函數(shù)調(diào)用記錄,即a函數(shù)調(diào)用位置變量等都不需要用到,則該調(diào)用棧中會(huì)只保留b函數(shù),這就叫做"尾調(diào)用優(yōu)化"(Tail call optimization),即只保留內(nèi)層函數(shù)的調(diào)用記錄。如果所有函數(shù)都是尾調(diào)用,那么完全可以做到每次執(zhí)行時(shí),調(diào)用記錄只有一項(xiàng),這將大大節(jié)省內(nèi)存。這就是"尾調(diào)用優(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)和任務(wù)隊(duì)列(task queue)

JS的異步機(jī)制由事件循環(huán)和任務(wù)隊(duì)列構(gòu)成.JS本身是單線程語言,所謂異步依賴于瀏覽器或者操作系統(tǒng)等完成. JavaScript 主線程擁有一個(gè)執(zhí)行棧以及一個(gè)任務(wù)隊(duì)列,主線程會(huì)依次執(zhí)行代碼,當(dāng)遇到函數(shù)時(shí),會(huì)先將函數(shù)入棧,函數(shù)運(yùn)行完畢后再將該函數(shù)出棧,直到所有代碼執(zhí)行完畢。

遇到異步操作(例如:setTimeout, AJAX)時(shí),異步操作會(huì)由瀏覽器(OS)執(zhí)行,瀏覽器會(huì)在這些任務(wù)完成后,將事先定義的回調(diào)函數(shù)推入主線程的任務(wù)隊(duì)列(task queue)中,當(dāng)主線程的執(zhí)行棧清空之后會(huì)讀取task queue中的回調(diào)函數(shù),當(dāng)task queue被讀取完畢之后,主線程接著執(zhí)行,從而進(jìn)入一個(gè)無限的循環(huán),這就是事件循環(huán).

However, 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".

Microtask 與 Macrotask

一個(gè)瀏覽器環(huán)境(unit of related similar-origin browsing contexts.)只能有一個(gè)事件循環(huán)(Event loop),而一個(gè)事件循環(huán)可以多個(gè)任務(wù)隊(duì)列(Task queue),每個(gè)任務(wù)都有一個(gè)任務(wù)源(Task source)。例如,客戶端可能實(shí)現(xiàn)了一個(gè)包含鼠標(biāo)鍵盤事件的任務(wù)隊(duì)列,還有其他的任務(wù)隊(duì)列,而給鼠標(biāo)鍵盤事件的任務(wù)隊(duì)列更高優(yōu)先級(jí),例如75%的可能性執(zhí)行它。這樣就能保證流暢的交互性,而且別的任務(wù)也能執(zhí)行到了。但是,同一個(gè)任務(wù)隊(duì)列中的任務(wù)必須按先進(jìn)先出的順序執(zhí)行。多個(gè)任務(wù)隊(duì)列,是為了方便控制優(yōu)先級(jí)。任務(wù)隊(duì)列是一個(gè)先進(jìn)先出的隊(duì)列.

macrotask 和 microtask 是異步任務(wù)的兩種分類。在掛起任務(wù)時(shí),JS 引擎會(huì)將所有任務(wù)按照類別分到這兩個(gè)隊(duì)列中,首先在 macrotask 的隊(duì)列(這個(gè)隊(duì)列也被叫做 task queue)中取出第一個(gè)任務(wù),執(zhí)行完畢后取出 microtask 隊(duì)列中的所有任務(wù)順序執(zhí)行;之后再取 macrotask 任務(wù),周而復(fù)始,直至兩個(gè)隊(duì)列的任務(wù)都取完。

全部代碼(script)是一個(gè)macrotask,js先執(zhí)行一個(gè)macrotask,執(zhí)行過程中遇到(setTimeout, setInterval, setImmediate等)異步操作則創(chuàng)建一個(gè)macrotask,遇到(process.nextTick, Promises等)創(chuàng)建一個(gè)microtask,這兩個(gè)queue分別被掛起.執(zhí)行棧為空時(shí)開始處理macrotask,完成后處理microtask,直到該microtask全部執(zhí)行完,然后繼續(xù)主線程調(diào)用棧.

注:每一次事件循環(huán)(one cycle of the event loop),只處理一個(gè) (macro)task。待該 macrotask 完成后,所有的 microtask 會(huì)在同一次循環(huán)中處理。處理這些 microtask 時(shí),還可以將更多的 microtask 入隊(duì),它們會(huì)一一執(zhí)行,直到整個(gè) microtask 隊(duì)列處理完。

兩個(gè)類別的具體分類如下:

macro-task: script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task: process.nextTick, Promises(這里指瀏覽器實(shí)現(xiàn)的原生 Promise), Object.observe, MutationObserver

參考文章:
Promise的隊(duì)列與setTimeout的隊(duì)列有何關(guān)聯(lián)?
node事件循環(huán)
深入淺出JavaScript事件循環(huán)機(jī)制(下)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85044.html

相關(guān)文章

  • [面試專題]JS異步原理(事件,隊(duì)列)

    摘要:全部代碼是一個(gè)先執(zhí)行一個(gè)執(zhí)行過程中遇到等異步操作則創(chuàng)建一個(gè)遇到等創(chuàng)建一個(gè)這兩個(gè)分別被掛起執(zhí)行棧為空時(shí)開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調(diào)用棧注每一次事件循環(huán),只處理一個(gè)。 JS異步原理(事件,隊(duì)列) 調(diào)用棧 JS執(zhí)行時(shí)會(huì)形成調(diào)用棧,調(diào)用一個(gè)函數(shù)時(shí),返回地址、參數(shù)、本地變量都會(huì)被推入棧中,如果當(dāng)前正在運(yùn)行的函數(shù)中調(diào)用另外一個(gè)函數(shù),則該函數(shù)相關(guān)內(nèi)容也會(huì)被推入棧頂.該函數(shù)執(zhí)...

    LeoHsiun 評(píng)論0 收藏0
  • [面試專題]JS異步原理(事件,隊(duì)列)

    摘要:全部代碼是一個(gè)先執(zhí)行一個(gè)執(zhí)行過程中遇到等異步操作則創(chuàng)建一個(gè)遇到等創(chuàng)建一個(gè)這兩個(gè)分別被掛起執(zhí)行棧為空時(shí)開始處理完成后處理直到該全部執(zhí)行完然后繼續(xù)主線程調(diào)用棧注每一次事件循環(huán),只處理一個(gè)。 JS異步原理(事件,隊(duì)列) 調(diào)用棧 JS執(zhí)行時(shí)會(huì)形成調(diào)用棧,調(diào)用一個(gè)函數(shù)時(shí),返回地址、參數(shù)、本地變量都會(huì)被推入棧中,如果當(dāng)前正在運(yùn)行的函數(shù)中調(diào)用另外一個(gè)函數(shù),則該函數(shù)相關(guān)內(nèi)容也會(huì)被推入棧頂.該函數(shù)執(zhí)...

    2json 評(píng)論0 收藏0
  • React專題:react,redux以及react-redux常見一些面試

    摘要:我們可以為元素添加屬性然后在回調(diào)函數(shù)中接受該元素在樹中的句柄,該值會(huì)作為回調(diào)函數(shù)的第一個(gè)參數(shù)返回。使用最常見的用法就是傳入一個(gè)對(duì)象。單向數(shù)據(jù)流,比較有序,有便于管理,它隨著視圖庫的開發(fā)而被概念化。 面試中問框架,經(jīng)常會(huì)問到一些原理性的東西,明明一直在用,也知道怎么用, 但面試時(shí)卻答不上來,也是挺尷尬的,就干脆把react相關(guān)的問題查了下資料,再按自己的理解整理了下這些答案。 reac...

    darcrand 評(píng)論0 收藏0
  • [面試專題]一線互聯(lián)網(wǎng)大廠面試總結(jié)

    摘要:道阻且長啊前端面試總結(jié)前端面試筆試面試騰訊一面瀏覽器工作原理瀏覽器的主要組件包括用戶界面包括地址欄后退前進(jìn)按鈕書簽?zāi)夸洖g覽器引擎用來查詢及操作渲染引擎的接口渲染引擎渲染界面和是基于兩種渲染引擎構(gòu)建的,使用自主研發(fā)的渲染引擎,和都使用網(wǎng)絡(luò)用來 道阻且長啊TAT(前端面試總結(jié)) 前端 面試 筆試 面試 騰訊一面 1.瀏覽器工作原理 瀏覽器的主要組件包括: 用戶界面- 包括地址欄、后退/前...

    lemanli 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<