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

資訊專欄INFORMATION COLUMN

Event Loop 那些事兒

tyheist / 2354人閱讀

摘要:消息隊(duì)列和事件循環(huán)異步過(guò)程中,工作線程在異步操作完成后需要通知主線程,那么這個(gè)通知機(jī)制是怎樣實(shí)現(xiàn)的呢答案是利用消息隊(duì)列和事件循環(huán)。

Event Loop 那些事兒

我們通常說(shuō) JavaScript 是單線程的,實(shí)際上是指在 JS 引擎中負(fù)責(zé)解釋和執(zhí)行 JS 代碼的線程只有一個(gè),一般成為主線程,在這種前提下,為了讓用戶的操作不存在阻塞感,前端 APP 的運(yùn)行需要依賴于大量的異步過(guò)程,所以當(dāng)然瀏覽器中還存在一些其他的線程,比如處理 http 請(qǐng)求的線程、處理 DOM 事件的線程、定時(shí)器線程、處理文件讀寫的 I/O 線程等等。

異步過(guò)程

一個(gè)異步過(guò)程通常是這樣的:

主線程發(fā)起一個(gè)異步請(qǐng)求,相應(yīng)的工作線程接收請(qǐng)求并告知主線程已收到;

主線程可以繼續(xù)執(zhí)行后面的代碼,同時(shí)工作線程執(zhí)行異步任務(wù);

工作線程完成工作后通知主線程,主線程收到通知后調(diào)用回調(diào)函數(shù)。

消息隊(duì)列和事件循環(huán)

異步過(guò)程中,工作線程在異步操作完成后需要通知主線程,那么這個(gè)通知機(jī)制是怎樣實(shí)現(xiàn)的呢?答案是利用消息隊(duì)列和事件循環(huán)。消息隊(duì)列是一個(gè)先進(jìn)先出的隊(duì)列,里面存放著各種消息,我們可以簡(jiǎn)單的理解為消息就是注冊(cè)異步任務(wù)時(shí)添加的回調(diào)函數(shù);事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中獲取消息、執(zhí)行回調(diào)的過(guò)程,之所以稱為事件循環(huán),就是因?yàn)樗?jīng)常被用類似如下方式來(lái)實(shí)現(xiàn):

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

消息隊(duì)列是一個(gè)存儲(chǔ)著待執(zhí)行任務(wù)的隊(duì)列,其中的任務(wù)嚴(yán)格按照時(shí)間先后順序執(zhí)行,排在隊(duì)頭的任務(wù)將會(huì)率先執(zhí)行,而排在隊(duì)尾的任務(wù)會(huì)最后執(zhí)行。消息隊(duì)列每次僅執(zhí)行一個(gè)任務(wù),在該任務(wù)執(zhí)行完畢之后,再執(zhí)行下一個(gè)任務(wù)。執(zhí)行棧則是一個(gè)類似于函數(shù)調(diào)用棧的運(yùn)行容器,當(dāng)執(zhí)行棧為空時(shí) JS 引擎便檢查消息隊(duì)列,如果不為空消息隊(duì)列便將第一個(gè)任務(wù)壓入執(zhí)行棧中運(yùn)行。

下面我們來(lái)看下述代碼來(lái)驗(yàn)證我們的想法:

setTimeout(function() {
    console.log(4)
}, 0);

new Promise(function(resolve) {
    console.log(1)

    for (var i = 0; i < 10000; i++) {
        i == 9999 && resolve()
    }

    console.log(2)
}).then(function() {
    console.log(5)
});

console.log(3);
比較吊詭的事情出現(xiàn)了,為什么結(jié)果是“1, 2, 3, 5, 4”,而不是“1, 2, 3, 4, 5”呢?!

按道理來(lái)說(shuō),執(zhí)行 setTimeout 時(shí)因?yàn)檠舆t為0,所以 console.log(4) 直接插入至消息隊(duì)列;創(chuàng)建 Promise 實(shí)例時(shí)同步執(zhí)行其函數(shù)體內(nèi)的代碼,先打印 1,再循環(huán)10000次后執(zhí)行 resolve 將 then 中的回調(diào)函數(shù) console.log(5) 插入至消息隊(duì)列,然后打印 2;最后執(zhí)行 console.log(3) 打印 3;在主線程執(zhí)行完成后讀取消息隊(duì)列,依次打印4和5。

上面的想法當(dāng)然是比較天真的,實(shí)際上瀏覽器中僅有一個(gè)事件循環(huán),然后消息隊(duì)列是可以有多個(gè)的。

macro-queue: script (整體代碼), setTimeout, setInterval, setImmediate, I/O, UI Rendering
micro-queue: process.nextTick, Promise, Object.observe, MutationObserver

并且 micro-queue 的任務(wù)優(yōu)先級(jí)高于 macro-queue 的任務(wù)優(yōu)先級(jí),這兩個(gè)任務(wù)隊(duì)列執(zhí)行順序如下:取1個(gè) macro-task 執(zhí)行之,然后把所有 micro-task 順序執(zhí)行完,再取 macro-task 中的下一個(gè)任務(wù),以此類推依次進(jìn)行。

優(yōu)先級(jí):process.nextTick > promise.then > setTimeout > setImmediate

Tip:process.nextTick 永遠(yuǎn)大于 promise.then 原因其實(shí)很簡(jiǎn)單:在 NodeJS 中,_tickCallback 在每一次執(zhí)行完 TaskQueue 中的一個(gè)任務(wù)后被調(diào)用,而在這個(gè)_tickCallback 中實(shí)質(zhì)上干了兩件事:

執(zhí)行掉 nextTickQueue 中所有任務(wù)

第一步執(zhí)行完后,執(zhí)行 _runMicrotasks 函數(shù)(執(zhí)行 micro-task 中的部分,即 promise.then 注冊(cè)的回調(diào))

總結(jié):瀏覽器環(huán)境一般只能有一個(gè)事件循環(huán)(實(shí)際上有兩類:browsing contexts 和 web workers),而一個(gè)事件循環(huán)可以多個(gè)任務(wù)隊(duì)列,每個(gè)任務(wù)都有一個(gè)任務(wù)源。相同任務(wù)源的任務(wù),只能放到一個(gè)任務(wù)隊(duì)列中;不同任務(wù)源的任務(wù),可以放到不同任務(wù)隊(duì)列中。舉個(gè)栗子,客戶端可能實(shí)現(xiàn)一個(gè)包含鼠標(biāo)鍵盤事件的任務(wù)隊(duì)列,還有其他的任務(wù)隊(duì)列,而給鼠標(biāo)鍵盤事件的任務(wù)隊(duì)列更高優(yōu)先級(jí),例如75%的可能性執(zhí)行它,這樣就能保證流暢的交互性,而且別的任務(wù)也能執(zhí)行到。

至此,再返回去看之前的代碼就不難分析出:代碼執(zhí)行開始把 setTimeout 的回調(diào)插入至 macro-queue 中,而打印完1后把 promise.then 的回調(diào)函數(shù)插入至 micro-queue 中,整體代碼執(zhí)行完后,按照消息隊(duì)列的優(yōu)先級(jí),先執(zhí)行 micro-task 即打印5,最后執(zhí)行 macro-task 即打印4。

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

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

相關(guān)文章

  • 關(guān)于Android消息機(jī)制的那些事兒

    摘要:關(guān)于中的消息機(jī)制就進(jìn)行到這里,下一篇將講講中的內(nèi)存泄漏問(wèn)題以及處理方法。 這幾天對(duì)handler有一些研究,寫出來(lái)供大家看看。 一、消息機(jī)制詳解 Android程序中,主要是通過(guò)消息機(jī)制來(lái)推動(dòng)整個(gè)程序運(yùn)作的。而消息機(jī)制中,完成主要功能的主要有以下幾個(gè)類: 1、Looper 2、Message、MessageQueue 3、handler 這是最基礎(chǔ)的幾個(gè)消息機(jī)制類,下面探究一下這幾個(gè)類...

    lushan 評(píng)論0 收藏0
  • 推送近期三波關(guān)于Vue.js的資訊

    摘要:原文來(lái)自集前端最近很火的框架資源定時(shí)更新,歡迎一下。推送自己整理近期三波關(guān)于的資訊這里就拋磚引玉了,望有更屌的資源送助攻。 原文來(lái)自:集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎Star一下。 推送自己整理近期三波關(guān)于Vue.js的資訊; 這里就拋磚引玉了,望有更屌的資源送助攻。 showImg(https://segmentfault.com/img/bVVeiZ); 第...

    Anonymous1 評(píng)論0 收藏0
  • 【回顧九月份第二周】 前端你該知道的事兒

    摘要:順便一說(shuō),這首歌的原唱是秋田,中島當(dāng)年嗓子壞了,才有這歌。中文是直接翻譯來(lái)的,作曲是秋田。一部電影春夏秋冬又一春春夏秋冬又一春是由金基德執(zhí)導(dǎo),金英民吳英秀金基德主演的一部韓國(guó)電影。年月日于韓國(guó)上映。 原鏈接: http://bluezhan.me/weekly/#/9-2 1、web前端 Angular vs. React vs. Vue: A 2017 comparison 9 S...

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

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

0條評(píng)論

tyheist

|高級(jí)講師

TA的文章

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