国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Event Loop 那些事兒

tyheist / 2350人閱讀

摘要:消息隊列和事件循環異步過程中,工作線程在異步操作完成后需要通知主線程,那么這個通知機制是怎樣實現的呢答案是利用消息隊列和事件循環。

Event Loop 那些事兒

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

異步過程

一個異步過程通常是這樣的:

主線程發起一個異步請求,相應的工作線程接收請求并告知主線程已收到;

主線程可以繼續執行后面的代碼,同時工作線程執行異步任務;

工作線程完成工作后通知主線程,主線程收到通知后調用回調函數。

消息隊列和事件循環

異步過程中,工作線程在異步操作完成后需要通知主線程,那么這個通知機制是怎樣實現的呢?答案是利用消息隊列和事件循環。消息隊列是一個先進先出的隊列,里面存放著各種消息,我們可以簡單的理解為消息就是注冊異步任務時添加的回調函數;事件循環是指主線程重復從消息隊列中獲取消息、執行回調的過程,之所以稱為事件循環,就是因為它經常被用類似如下方式來實現:

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

消息隊列是一個存儲著待執行任務的隊列,其中的任務嚴格按照時間先后順序執行,排在隊頭的任務將會率先執行,而排在隊尾的任務會最后執行。消息隊列每次僅執行一個任務,在該任務執行完畢之后,再執行下一個任務。執行棧則是一個類似于函數調用棧的運行容器,當執行棧為空時 JS 引擎便檢查消息隊列,如果不為空消息隊列便將第一個任務壓入執行棧中運行。

下面我們來看下述代碼來驗證我們的想法:

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);
比較吊詭的事情出現了,為什么結果是“1, 2, 3, 5, 4”,而不是“1, 2, 3, 4, 5”呢?!

按道理來說,執行 setTimeout 時因為延遲為0,所以 console.log(4) 直接插入至消息隊列;創建 Promise 實例時同步執行其函數體內的代碼,先打印 1,再循環10000次后執行 resolve 將 then 中的回調函數 console.log(5) 插入至消息隊列,然后打印 2;最后執行 console.log(3) 打印 3;在主線程執行完成后讀取消息隊列,依次打印4和5。

上面的想法當然是比較天真的,實際上瀏覽器中僅有一個事件循環,然后消息隊列是可以有多個的。

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

并且 micro-queue 的任務優先級高于 macro-queue 的任務優先級,這兩個任務隊列執行順序如下:取1個 macro-task 執行之,然后把所有 micro-task 順序執行完,再取 macro-task 中的下一個任務,以此類推依次進行。

優先級:process.nextTick > promise.then > setTimeout > setImmediate

Tip:process.nextTick 永遠大于 promise.then 原因其實很簡單:在 NodeJS 中,_tickCallback 在每一次執行完 TaskQueue 中的一個任務后被調用,而在這個_tickCallback 中實質上干了兩件事:

執行掉 nextTickQueue 中所有任務

第一步執行完后,執行 _runMicrotasks 函數(執行 micro-task 中的部分,即 promise.then 注冊的回調)

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94334.html

相關文章

  • 關于Android消息機制的那些事兒

    摘要:關于中的消息機制就進行到這里,下一篇將講講中的內存泄漏問題以及處理方法。 這幾天對handler有一些研究,寫出來供大家看看。 一、消息機制詳解 Android程序中,主要是通過消息機制來推動整個程序運作的。而消息機制中,完成主要功能的主要有以下幾個類: 1、Looper 2、Message、MessageQueue 3、handler 這是最基礎的幾個消息機制類,下面探究一下這幾個類...

    lushan 評論0 收藏0
  • 推送近期三波關于Vue.js的資訊

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

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

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

    sixgo 評論0 收藏0

發表評論

0條評論

tyheist

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<