面試經典:Event Loop

jsliang發表於2019-12-15

歡迎關注 jsliang 的文件庫 —— 一個窮盡一生更新的倉庫,檢視更多技術、理財、健身文章:github.com/LiangJunron…

一 目錄

不折騰的前端,和鹹魚有什麼區別

目錄
一 目錄
二 前言
三 Event Loop
四 瀏覽器 Event Loop
4.1 示例 1
4.2 示例 2
4.3 示例 3
4.4 小結
五 Node.js Event Loop
5.1 setTimeout & setImmediate
5.2 process.nextTick()
5.3 示例 1
5.4 示例 2
5.5 小結
六 總結
七 參考文獻

二 前言

返回目錄

Hello 小夥伴們早上好、中午好、下午好、晚上好、凌晨好~

在日常工作中,你有沒有碰到過這種疑惑:

  • 疑惑一:為什麼這份程式碼它不按照我的意思走?為啥不是輸出 1 2 3
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 3
// 3
// 3
複製程式碼
  • 疑惑二:為什麼這份程式碼它也不按照我的意思走?為啥不是輸出 jsliang
let name;

setTimeout(() => {
  name = '樑峻榮';
  console.log(name);
}, 1000);

if (name) {
  name = 'jsliang';
  console.log(name);
}
// console: '樑峻榮'
複製程式碼

孩子沒娘,說來話長。

既然說來話長,jsliang 只能嘗試長話短說了:

  • 本篇文章從 Event Loop 起因說起,通過探討 瀏覽器環境 Event Loop 和 Node.js 環境 Event Loop,從而解惑工作中產生的困擾,擴充套件你面試知識點。

這麼一說,我們也好對文章進行劃分了:

  • 第三章 Event Loop:解釋 Event Loop 產生原因和程式碼演示。
  • 第四章 瀏覽器 Event Loop:解惑工作困擾和擴充套件必備面試知識點。
  • 第五章 Node.js Event Loop:進一步探索瀏覽器和 Node.js 中 Event Loop 的不同。

OK,Let's go!

三 Event Loop

返回目錄

  • 問:什麼是 Event Loop,為什麼需要 Event Loop?

答:

首先,我們需要知道的是:JavaScript 是單執行緒的。

單執行緒意味著,所有任務都需要排隊,前一個任務結束,才會執行後一個任務。

假設 jsliang 和 JavaScript 一樣一次只能做一件事,那麼大概就是如下圖所示。

面試經典:Event Loop

而這種 主執行緒從 “任務佇列” 中讀取執行事件,不斷迴圈重複的過程,就被稱為 事件迴圈(Event Loop)

然後,如果前一個任務耗時很長,後一個任務就不得不一直等著,那麼我們肯定要對這種情況做一些特殊處理,畢竟很多時候我們並不是完全希望它如此執行。

所以為了協調事件(event),使用者互動(user interaction),指令碼(script),渲染(rendering),網路(networking)等,使用者代理(user agent)必須使用事件迴圈(event loops)。

這樣,在瞭解 瀏覽器 Event LoopNode.js Event Loop 的情況下,我們就可以瞭解它的執行過程。

通過自身的瞭解,來處理一些較為棘手的問題。

為了加深小夥伴們的印象,可以看下圖:

面試經典:Event Loop

jsliang 日常中,強制被加上了 “被豆豆媽打”(廢話,豆豆那麼可愛,你怎麼可以打豆豆)。

當然,這個被打的順序也不一定是在後面,可能打多兩次後,“睡覺” 完之後就是 “被豆豆媽打” 了。

通過這個解釋,小夥伴們應該知道為啥有 瀏覽器 Event LoopNode.js Event Loop 了。

等等,你剛才說到了 瀏覽器 Event LoopNode.js Event Loop,為什麼都是關於 JavaScript 的,在這兩部分都不一樣呢?

  • 簡單來說:你的頁面放到了瀏覽器去展示,你的資料放到了後臺處理(將 Node.js 看成 PHP、Java 等後端語言),這兩者能沒有區別麼?!

你說了跟沒說一樣,為什麼會這樣你沒有解釋啊!

好的,說得再仔細點:

  • Node.js:Node.js 的 Event Loop 是基於 libuv。libuv 已經對 Event Loop 作出了實現。
  • 瀏覽器:瀏覽器的 Event Loop 是基於 HTML5 規範的。而 HTML5 規範中只是定義了瀏覽器中的 Event Loop 的模型,具體實現留給了瀏覽器廠商。

libuv 是一個多平臺支援庫,主要用於非同步 I/O。它最初是為 Node.js 開發的,現在 Luvit、Julia、pyuv 和其他的框架也使用它。Github - libuv 倉庫

恍然大悟,的確是不一樣的啊!

所以,我們們得將這兩個 Event Loop 區分開來,它們是不一樣的東東哈~

最後,我們們解疑開頭的兩個問題,為什麼會這樣子,有沒辦法解決?

  • 疑惑一:為什麼這份程式碼它不按照我的意思走?為啥不是輸出 1 2 3
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 3
// 3
// 3
複製程式碼

這道題是面試常備題,它是個很有意思的問題,不僅可以讓面試官跟你閒聊到 Event Loop,也可以閒聊下 var let const

為此,jsliang 特意錄製了一個 GIF,希望能幫助小夥伴進一步探索這個機制:

面試經典:Event Loop

軟體是 VS Code,除錯方式是 Node.js

請仔細觀看 GIF 圖:

  1. 在執行 for 遍歷的時候,它先執行了和 setTimeout 同級的 console,然後往下執行,到 setTimeout 的時候,跳過了(放到某個位置)setTimeout,依次列印了 0, 1, 2
  2. 步驟 1 跳過的三次 setTimeout 開始執行,但是這時候的 i 的值,經過前面的 i++ 後,變成了 3for 中止迴圈後,i 已經是 3 了)。所以,再依次列印了 3 3 3

就是說,先走了正常的 for,然後碰到 setTimeout 時,將 setTimeout 依次放到了異次元,最後走完 for 後,再將異次元中的的 setTimeout 放出,依次將數字給輸出了。

這個執行機制,就是 Event Loop 的影響,恍然大悟有木有~

這個問題的精妙之處在於,它不僅可以問你關於 Event Loop 的部分,還可以考察你對於 ES6 的 let 和 ES5 的 var 的區分,因為它有一個解決方式就是使用了 ES6 的 let

解決這個問題之前,不妨思考下下面的輸出:

for (var i = 0; i < 3; i++) {

}
for (let j = 0; j < 3; j++) {

}
console.log(i);
console.log(j);
複製程式碼

如果小夥伴對 ES6 有些許瞭解,應該不難猜出:

3
ReferenceError: j is not defined
複製程式碼

是不是有些想法,那麼我們們再看下下面的解決方法,再進行總結:

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 0
// 1
// 2
複製程式碼

是的,將 var i 改成了 let i 後,輸出的結果依次是 0 1 2 了。

為什麼呢?簡單回覆就是:

letfor 中形成了獨特的作用域塊,當前的 i 只在本輪迴圈中有效,然後 setTimeout 會找到本輪最接近的 i,從而作出了正確的輸出。

而我們通過 var 進行的定義,它會汙染全域性變數,所以在 for 外層,還可以看到 i 的值。

當然,講到這裡,你可能還是不太清楚更細節的區分,亦或者面試官進一步問你 var let const 的區分了,你要怎麼更好回答?

看看阮一峰大佬的 ES6 文件吧:es6.ruanyifeng.com/#docs/let

這裡就不哆嗦了,有空我再將 ES6 這塊內容整理到我的文件庫中,歡迎持續關注 jsliang 的文件庫:github.com/LiangJunron…

  • 疑惑二:為什麼這份程式碼它也不按照我的意思走?為啥不是輸出 樑峻榮
let name;

setTimeout(() => {
  name = 'jsliang';
  console.log(name);
}, 1000);

if (name) {
  name = '樑峻榮';
  console.log(name);
}
// console: 'jsliang'
複製程式碼

當你瞭解產生疑惑一的原因後,疑惑二也就不破而解了。

我們希望的是 JavaScript 按照我們需要的順序寫,結果它並沒有,就是因為受到了 Event Loop 的影響。

JavaScript 在碰到 setTimeout 的時候,會將它封印進異次元,只有等所有正常的語句(iffor……)執行完畢後,才會將它從異次元解封,輸出最終結果。

咦,這就有意思了,瀏覽器的異次元和 Node.js 的異次元都是怎樣的呢?我們一起往下看。

四 瀏覽器 Event Loop

返回目錄

在講解瀏覽器的 Event Loop 前,我們需要先了解一下 JavaScript 的執行機制:

  1. 所有同步任務都在主執行緒上執行,形成一個 “執行棧”(execution context stack)。
  2. 主執行緒之外,存在一個 “任務佇列”(task queue),在走主流程的時候,如果碰到非同步任務,那麼就在 “任務佇列” 中放置這個非同步任務。
  3. 一旦 “執行棧” 中所有同步任務執行完畢,系統就會讀取 “任務佇列”,看看裡面存在哪些事件。那些對應的非同步任務,結束等待狀態,進入執行棧,開始執行。
  4. 主執行緒不斷重複上面三個步驟。

而 JavaScript 的非同步任務,還細分兩種任務:

  • 巨集任務(Macrotask)script(整體程式碼)、setTimeoutsetIntervalXMLHttpRequest.prototype.onloadI/O、UI 渲染
  • 微任務(Microtask)PromiseMutationObserver

這麼講是不太容易理解的,我們們上圖:

面試經典:Event Loop

圖較大,如果是公眾號看的小夥伴,可以點選【閱讀原文】看全圖

好的,如果小夥伴們看不清楚,那麼我們們還是通過程式碼來進行講解,畢竟以上屬於 jsliang 個人理解,是從 15 篇以上文章和自己觀察程式碼執行總結出來的。

4.1 示例 1

返回目錄

那麼,上程式碼~

示例 1

// 位置 1
setTimeout(function () {
  console.log('timeout1');
}, 1000);

// 位置 2
console.log('start');

// 位置 3
Promise.resolve().then(function () {
  // 位置 5
  console.log('promise1');
  // 位置 6
  Promise.resolve().then(function () {
    console.log('promise2');
  });
  // 位置 7
  setTimeout(function () {
    // 位置 8
    Promise.resolve().then(function () {
      console.log('promise3');
    });
    // 位置 9
    console.log('timeout2')
  }, 0);
});

// 位置 4
console.log('done');
複製程式碼

提問:請指出上面程式碼的輸出結果?

回答

這是經典的面試題型,所以我們們看到不用慌,先拿我們上面的點,區分下分巨集任務和微任務:

  • 巨集任務(Macrotask)script(整體程式碼)、setTimeoutsetIntervalXMLHttpRequest.prototype.onloadI/O、UI 渲染
  • 微任務(Microtask)PromiseMutationObserver

OK,開始走流程:

如果你覺得文字不好理解,請往下翻,有 GIF 圖演示!!!

  1. 首先碰到的是 script(整體程式碼),先看【位置 1】,屬於巨集任務 setTimeout 下的,所以做個標記,待會回來執行。
  2. 接著碰到【位置 2】,這是 script(整體程式碼)下的無阻礙程式碼,直接執行即可。
  3. 再來碰到【位置 3】,它現在是 script(整體程式碼)下的微任務,所以我們們做個標記,走完檔案所有程式碼後,優先執行微任務,再執行巨集任務。
  4. 最後碰到【位置 4】,它是 script(整體程式碼)下的無阻礙程式碼,直接執行即可。

這樣,第一波步驟,我們輸出的是【位置 2】的 start 和【位置 4】的 done

我們接著走:

  1. 上面我們走完了第一遍程式碼,然後現在這一步先走 script(整體程式碼)下的微任務,即【位置 3】
    1. 先碰到【位置 5】,這是無阻礙程式碼,直接執行。
    2. 再碰到【位置 6】,這是微任務,標記一下,等下執行完【位置 3】內所有程式碼後,優先執行它。
    3. 最後碰到【位置 7】,這是巨集任務,丟入任務佇列,看它和【位置 1】誰先走了。
  2. 走完一遍【位置 3】後,發現還有微任務【位置 6】,所以執行【位置 6】,進行列印輸出。

到這一步,我們就走完了 script(整體程式碼)及之下的所有微任務了。

這時候,我們會說,【位置 1】和【位置 7】都被丟到任務佇列了,是不是【位置 1】先走呢?

答案為:不是的。

同樣的 setTimeoutjsliang 在測試的時候,就發現它們的輸出結果在各個環境都有自己的流程,有時候先走【位置 7】,再走【位置 1】;而有時候先走【位置 1】,再走【位置 7】。

當然,如果你指定是在 Chrome 的控制檯輸出一下上面的程式碼,那就是先【位置 7】,再【位置 1】~

  • point:不要主觀臆斷某個程式碼會怎麼走,最好還是直接實況執行走一波!
  1. 先走【位置 7】。碰到【位置 8】,將其新增到【位置 7】的微任務中,等【位置 7】所有程式碼執行完畢回來優先走微任務;碰到【位置 9】,這是無阻礙程式碼,直接輸出即可。
  2. 執行【位置 7】的微任務【位置 8】,輸出對應文字。
  3. 最後走【位置 1】,輸出對應文字。

所以答案是:

start
done
promise1
promise2
timeout2
promise3
timeout1
複製程式碼

你猜對沒有?

沒有可以看下 GIF 圖加深印象:

面試經典:Event Loop

4.2 示例 2

返回目錄

在上面,jsliang 花費了許多口水,講了一些繁雜冗餘的步驟,所以下面這個示例,請小夥伴們先自行猜設,得出結論後再翻看答案和除錯 GIF~

示例 2

console.log("script start");

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

setTimeout(function() {
  console.log("setTimeout---200");
  setTimeout(function() {
    console.log("inner-setTimeout---0");
  });
  Promise.resolve().then(function() {
    console.log("promise5");
  });
}, 200);

Promise.resolve()
  .then(function() {
    console.log("promise1");
  })
  .then(function() {
    console.log("promise2");
  });
Promise.resolve().then(function() {
  console.log("promise3");
});
console.log("script end");
複製程式碼



  • 輸出結果
script start
script end
promise1
promise3
promise2
setTimeout---0
setTimeout---200
promise5
inner-setTimeout---0
複製程式碼
  • GIF 演示

面試經典:Event Loop

4.3 示例 3

返回目錄

最後再看一個示例:

示例 3

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

const promise = new Promise(function executor(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
複製程式碼

如果不常用 Promise 的小夥伴,可能對此感到疑惑,為啥不是:3 1 2 5 4

手動滑稽,別問,問就是進一步探索 Promise

當然,還沒將所有探索結果更新,如果有小夥伴催更會加快速度,歡迎留言或者私聊催更,哈哈~

4.4 小結

返回目錄

這樣,我們就通過 3 個示例,大致瞭解了瀏覽器的 Event Loop。

當然,實際應用中的程式碼,何止這麼簡單,甚至有時候,面試官給你的面試題,也會讓你瞠目結舌。

所以,這裡我們們廢話兩點:

  1. 你可以瞭解巨集任務和微任務的大體執行,例如先走 if...else...,再走 Promise……但是,詳細到每個 point 都記下來,這裡不推薦。大人,時代在進步,記住死的不如多在業務實踐中嘗試,取最新的知識。
  2. 瀏覽器的 Event Loop 和 Node.js 的 Event Loop 不同,萬一哪天 XX 小程式搞另類,有自己的 Event Loop,你要一一記住嗎?

碰到問題不要慌,程式設計師,折騰就對了~

五 Node.js Event Loop

返回目錄

那麼,下面我們們吐槽下 Node.js 的 Event Loop。

說實話,看完 Node 官網和大佬們關於 Node.js 的 Event Loop 講解,讓我想起了 Vue、React、微信小程式 的【生命週期】,再聯想到我們的人生彷彿就像被寫死的程式一樣週期性、事件性執行,非常可惡,哈哈~

上面我們講解過:Node.js 的 Event Loop 是基於 libuv。libuv 已經對 Event Loop 作出了實現。

那麼其機制是怎樣子的呢?看圖:

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
複製程式碼

關於這 6 個階段,官網描述為:

  • 定時器(timers):本階段執行已經被 setTimeout()setInterval() 的排程回撥函式。
  • 待定回撥(pending callbacks):執行延遲到下一個迴圈迭代的 I/O 回撥。
  • idle, prepare:僅系統內部使用。
  • 輪詢(poll):檢索新的 I/O 事件;執行與 I/O 相關的回撥(幾乎所有情況下,除了關閉的回撥函式,那些由計時器和 setImmediate() 排程的之外),其餘情況 Node 將在適當的時候在此阻塞。
  • 檢測(check)setImmediate() 回撥函式在這裡執行。
  • 關閉的回撥函式(close callbacks):一些關閉的回撥函式,如:socket.on('close', ...)

當然,這裡 jsliang 並不想畫蛇添足,將官網或者其他大佬的文章照搬過來說是自己的,推薦小夥伴們閱讀官閘道器於 Event Loop 的各個階段的描述,以期在工作中有所使用:

Node.js 在不停的探索中,也會有所更新,所以正應了 jsliang 在瀏覽器 Event Loop 中的小結所說:不要限定死自己的知識點,與時俱進才是王道

Node.js v9.5.0 Event Loop

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
複製程式碼

但是,迫於生活所需,有些時候,前端面試官還是會跟你扯 setTimeout & setImmediateprocess.nextTice()

5.1 setTimeout & setImmediate

返回目錄

  • setTimeout:眾所周知,這是一個定時器,指定 n 毫秒後執行定時器裡面的內容。
  • setImmediate:Node.js 發現使用 setTimeoutsetInterval 有些小弊端,所以設計了個 setImmediate,該方法被設計為一旦在當前輪詢階段完成,就執行這個指令碼。

當然,光說無益,看程式碼:

index.js

setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});
複製程式碼

猜測下在 VS Code 中執行 node index.js 命令會發生什麼?

結局 1

immediate
timeout
複製程式碼

結局 2

timeout
immediate
複製程式碼

事實上這兩個結局都是會存在的,看似 happy ending,但是有的小夥伴可能心裡鬧翻天。

按照官網的解釋:

  • 執行計時器的順序將根據呼叫它們的上下文而異。
  • 如果兩則都從主模組內呼叫,則計時器將受到程式效能的約束(這可能會受到計算機上其他正在執行應用程式的影響)。
  • 如果你將這兩個函式放入一個 I/O 迴圈內呼叫,setImmediate 總是被有限呼叫。
const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('timeout');
  }, 0);
  setImmediate(() => {
    console.log('immediate');
  });
});
複製程式碼

雖然官方解釋的很 巧妙,但是不管你懂不懂,反正我覺得有點扯淡。

最後再來句官方總結:

  • 使用 setImmediate() 相對於 setTimeout 的主要優勢是:如果 setImmediate() 是在 I/O 週期內被排程的,那麼它將會在任何的定時器之前執行,跟這裡存在多少個定時器無關。

enm...後面如果我具體使用 Node.js 的時候,我再進一步觀察吧,至於現在,我還是先了解下即可。

5.2 process.nextTick()

返回目錄

nextTick 比較特殊,它存有自己的佇列。

並且,它獨立於 Event Loop,無論 Event Loop 處於何種階段,都會在階段結束的時候清空 nextTick 佇列。

還有需要注意的是:process.nextTick() 優先於其他的微任務(microtask)執行。

當然,如果你對此有所興趣,你可以進一步探索原始碼,或者觀察大佬們探索原始碼:

沒有使用就沒有發言權,作為一個 Node.js 菜雞,這裡就不妄加評論分析了。

5.3 示例 1

返回目錄

下面開始示例,我們看下 Node.js 的 Event Loop 有何差異:

示例 1

setTimeout(() => {
  console.log("timer1");
  Promise.resolve().then(function() {
    console.log("promise1");
  });
});

setTimeout(() => {
  console.log("timer2");
  Promise.resolve().then(function() {
    console.log("promise2");
  });
});
複製程式碼

如果你還記得上面講解的瀏覽器的 Event Loop,你可能會將答案直接寫成:

瀏覽器 Event Loop 輸出:

timer1
promise1
timer2
promise2
複製程式碼

是的你是對的,那就是瀏覽器的 Event Loop,到了 Node.js 這塊,就有不同變化了:

Node.js Event Loop 輸出:

timer1
timer2
promise1
promise2
複製程式碼

嘗試接受它!

然後大聲默唸:根據具體環境進行對應觀察和得出結論

5.4 示例 2

返回目錄

下面我們們再看一個示例:

示例 2

setTimeout(function () {
   console.log(1);
});
console.log(2);
process.nextTick(() => {
   console.log(3);
});
new Promise(function (resolve, rejected) {
   console.log(4);
   resolve()
}).then(res=>{
   console.log(5);
})
setImmediate(function () {
   console.log(6)
})
console.log('end');
複製程式碼

node index.js

2
4
end
3
5
1
6
複製程式碼

這裡不打算解析,因為我怕初識 Event Loop 的小夥伴看完解釋後懵逼,然後搞混淆了。

實話:我也不敢解析,因為我就是 Node.js 菜雞

5.5 小結

返回目錄

終上所述,我們進行小結:

Node 端事件迴圈中的非同步佇列也是這兩種:Macrotask(巨集任務)佇列和 Microtask(微任務)佇列。

  • 常見的 Macrotask:setTimeoutsetIntervalsetImmediatescript(整體程式碼)、 I/O 操作等。
  • 常見的 Microtask:process.nextTicknew Promise().then(回撥) 等。

OK,我們們就探索了一遍 Node.js 的 Event Loop 啦,但是因為我們還成就不了 Node.js 工程師,所以我們就不對其進行詳細探索,以免和瀏覽器的 Event Loop 混淆了。

感興趣的小夥伴可以自行探索咯~

六 總結

返回目錄

如果你看到這裡,你已經近乎懵逼,那麼,還是那個建議:

  • 不管 Event Loop 在瀏覽器亦或者 Node.js 表現機制,最好的操作還是在對應環境中進行嘗試。

你不能完全保證你的記憶力是 OK 的,所以你只需要知道有這個問題,然後在工作中實踐解決即可。

enm...所以你看完了一篇水文,唯一的作用是讓你面試的時候,能愉快地玩耍一些簡單題目~

哈哈,Good luck.

如果你覺得我的文章還不錯,想持續關注或者加我微信好友,歡迎前往 github.com/LiangJunron… 進行 star 或者加微信。

七 參考文獻

返回目錄

感謝以下大佬們的文章,讓我受益頗多。

並在他們創作的基礎上,基於自己的想法,進行了整合。

  1. 《Tasks, microtasks, queues and schedules》 - Jake
  2. 《徹底搞懂瀏覽器 Event-loop》 - 劉小夕
  3. 《徹底理解 JS Event Loop(瀏覽器環境)》 - 93
  4. 《徹底弄懂瀏覽器端的 Event-Loop》 - 長可
  5. 《什麼是瀏覽器的事件迴圈(Event Loop)?》 - 魚子醬
  6. 《理解event loop(瀏覽器環境與nodejs環境)》 - sugerpocket
  7. 《從 event loop 規範探究 JavaScript 非同步及瀏覽器更新渲染時機》 - 楊敬卓
  8. 《跟著 Event loop 規範理解瀏覽器中的非同步機制》 - fi3ework
  9. 《不要混淆 nodejs 和瀏覽器中的 event loop》 - youth7
  10. 《瀏覽器的 event loop 和 node 的 event loop》 - 金大光
  11. 《瀏覽器與 Node 的事件迴圈(Event Loop)有何區別?》 - 浪裡行舟
  12. 《瀏覽器和 Node 不同的事件迴圈(Event Loop)》 - toBeTheLight
  13. 《let 和 const 命令》 - 阮一峰
  14. 《Node.js Event Loop》 - Node.js 官網

不折騰的前端,和鹹魚有什麼區別!

面試經典:Event Loop

jsliang 會每天更新一道 LeetCode 題解,從而幫助小夥伴們夯實原生 JS 基礎,瞭解與學習演算法與資料結構。

浪子神劍 會每天更新面試題,以面試題為驅動來帶動大家學習,堅持每天學習與思考,每天進步一點!

掃描上方二維碼,關注 jsliang 的公眾號(左)和 浪子神劍 的公眾號(右),讓我們一起折騰!

知識共享許可協議
jsliang 的文件庫樑峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可。
基於github.com/LiangJunron…上的作品創作。
本許可協議授權之外的使用許可權可以從 creativecommons.org/licenses/by… 處獲得。

相關文章