《譯》驚豔!動態圖演示 - 事件循環 Event Loop

前言

對於事件循環,這是每一個 JavaScript 開發人員必然會遇到或者須要理解的內容之一。javascript

可是對於初級開發者來講,理解起來可能有些混亂。java

由於我是一個視覺學習者,因此我經過低分辨率 gif 圖的可視化方式來幫助你理解它。git

事件循環

可是首先,事件循環是什麼,爲何要關心呢?github

JavaScript 是 單線程的:一次只能運行一個任務。瀏覽器

一般,這沒什麼大不了的,可是如今想象你正在運行一個耗時 30 秒的任務。數據結構

在此任務中,咱們等待 30 秒才能進行其餘任何操做(默認狀況下,JavaScript 在瀏覽器的主線程上運行,所以整個用戶界面都停滯了)😬 。異步

都到 2020 年了,沒有人想停留在一個速度慢,交互反應遲鈍的網站。函數

幸運的是,瀏覽器爲咱們提供了JavaScript 引擎自己不提供的一些功能:Web API。oop

這包括 DOM API,setTimeout HTTP 請求等,這能夠幫助咱們建立一些異步的,非阻塞的行爲。post

當咱們調用一個函數時,它會被添加到稱爲 調用棧 的數據結構中。

調用棧是 JS 引擎的一部分,這不是特定於瀏覽器的。

它是一個調用棧,這意味着它是 先進先出 的(例如一堆煎餅)。

當一個函數返回一個值時,它會從調用棧中彈出 👋。

respond 函數返回一個 setTimeout 函數。

setTimeout 由 Web API 提供給咱們:它讓咱們拖延的任務,而不會阻塞主線程。

咱們傳遞給該 setTimeout 函數的回調函數,箭頭函數 () => { return "Hey" } 已添加到 Web API。

同時,該 setTimeout 函數和 response 函數從調用棧中彈出,它們都返回了它們的值!

在 Web API中,計時器的運行時間與咱們傳遞給它的第二個參數 1000ms 同樣長。回調不會當即添加到調用棧中,而是會傳遞給稱爲隊列的東西。

這多是一個使人困惑的部分:這並不意味着在 1000 毫秒後將回調函數添加到調用棧中(從而返回一個值)!它只是在 1000 毫秒後添加到 隊列中。但這是一個隊列,該功能必須等待輪到它!

接下爲是咱們一直在等待的重點內容……

讓事件循環執行其惟一的任務了:將隊列與調用棧鏈接起來!若是調用棧爲 ,那麼若是全部先前調用的函數都返回了它們的值並已從堆棧中彈出,則隊列中的 第一項 將添加到調用棧中,在這種狀況下,沒有其餘函數被調用,這意味着當回調函數成爲隊列中的第一項時,調用棧爲空。

回調被添加到調用棧中,被調用,並返回一個值,並從調用棧中彈出。


例子

閱讀一篇文章頗有趣,可是經過反覆地實際操做,你會對此理解得更深。

若是運行如下 js,請想一下控制檯會輸出什麼內容:

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

bar();
foo();
baz();
複製代碼

想出答案了嗎?

讓咱們快速看一下在瀏覽器中運行此代碼時發生的過程:

  1. 咱們調用 barbar 返回一個 setTimeout 函數。

  2. 咱們傳遞給的回調 setTimeout 被添加到 Web API,該 setTimeout 函數中,並 bar 從調用堆棧中彈出。

  3. 計時器運行,同時 foo 調用並記錄 Firstfoo 返回(未定義),baz 被調用,並將回調添加到隊列中。

  4. baz 輸出 Third,事件循環看到 baz 返回後調用棧爲空,而後將回調添加到調用棧。

  5. 回調再打印出 Second


但願這會使你對事件循環的理解更加清析!最重要的是 瞭解某些錯誤 / 行爲可能從何而來

當遇到不明白的地方時,也能 高效地Google 上搜索正確的關鍵字 ,並能搜索到正確的答案 💪🏼 。

最後

外國友人技術博客的語言表達的方式和風格、與國人的仍是有很大差異的啊。

姐妹篇:驚豔!可視化的 js:動態圖演示 Promises & Async/Await 的過程!

翻譯了兩篇文章,仍是蠻有趣的 😇,瞬間感受本身的英文水平高達 8 級了啦 (白日夢 🤩)。

推薦閱讀: 經過10 個實例小練習,快速入門熟練 Vue3 核心新特性

支持一下下👇

相關文章
相關標籤/搜索