Javascript : Event Queue & Event Loop

閱讀時間約 7 分鐘

前言

這是第一次寫技術文章,但其實應該也只能說是蒐集很多資料並學習如何透過自己的話解釋的內容,並不能像其他大神可能分享一些很酷的技術,目標就單純是為了完成最後一週的作業(如下)。
setTimeout(function(){console.log('delay 0 sec')}, 0)
console.log('Hello!')
透過兩天左右的閱讀資料讓自己對JS在同步與非同步有更多概念,由於有許多專有名詞,因此會先針對各專有名詞作介紹,再敘述自己的看法,最後提供這次參考的網路資源

走入非同步之前

執行環境(Execution Context)
Javascript被執行的地方,在Chrome裡,就是由V8 Engine提供此環境,任何程式碼被執行與讀取的地方都是執行環境,其中又可分為下列三種類型:
  • 全域執行環境 : 預設的執行環境,也就是一開始載入JS檔案的執行環境就是全域執行環境,不在任何函式裡面的程式碼就是在全域執行環境,其功用除了創造全域變數,還會進行記憶體的指派。
  • 函式執行環境 : 就如字面上的意思,即函式被呼叫執行的環境,此執行環境可存在很多個,須注意的是其並不會產生全域物件。
  • eval函式執行環境 : eval對開發者來說是非常方便的函式,可以透過字串方式執行JS,需注意的是如透過EVAL綁定的資料未經過適當編碼與驗證,可能造成注入攻擊的產生,因此現在也較不被推薦使用,甚至在CSP(Content Security Policy,可看成Server回送給Cliet端的Http header裡面的一種安全規範)裡面已經被預設為禁止使用。
執行環境堆疊 (Execution stack)
上面提到函式執行環境可能有很多個,每一個函式被呼叫就會產生一個與之對應的執行環境,此時會透過「堆疊」這種資料結構來儲存函式執行環境,為一種「後進先出」的資料結構。
單線程 (Single-Thread)
一次只能做一件事情,如果有很多事情就會進行排隊,再逐一執行。
非同步(Asynchronous)
即為同一時間可以處理不只一件事情(註: 其他事情亦非同時進行),這在串接第三方API教材的時候就有用到,利用Ajax可以讓瀏覽器向server送出請求時,不需要等待結果仍然可以處裡其他事情,待之後收到response之後,新的內容可以隨時更新至網頁,這也是為什麼瀏覽Facebook、Gmail的時候不需要看到網頁一直重新整理。
Javascript Runtime Environment (JRE)
JRE即為Javascript執行的環境,最常使用的runtiime就是瀏覽器。我們在宣告函數時,使用到的let、const、function、if else,這些都是Javascript的一部分,但其實之前常常使用到的DOM、console.log、這些其實都不是Javascript,而是瀏覽器這個runtime開放給 Javascript 的 API。也就是說不同的runtime會提供不同的東西,例如瀏覽器的DOM就不能再Node.js執行。

研究分享

Javascript是一個同步的程式語言,代表同一時間只做一件事情,也就是一次只跑一段程式碼。但想想如果我們在讀取Facebook網頁,JS除了要渲染畫面還要透過Http請求跟後端拿資料,但如果文章資料很多的時候,在取得所有資料前就都會無法執行其他任務,造成Blocking的現象,因此JS其實也是有非同步執行的能力,讓使用者瀏覽網頁更為順暢。至於如何處理「同步」與「非同步」的動作呢,就要透過我們今天的主角 —Event Queue、 Event Loop。
上面的名詞解釋曾提到DOM其實不算Javascript語言,而是瀏覽器提供的API,讓我們使用者可以在開發時直接使用,其較常使用的API有操作DOM節點的API — document.querySelector、計時的API — setTimeout、 AJAX相關 — XMLHttpRequest。這些由runtime提供的API,不會影響主執行環境的運行,讓網頁可以同時做很多事情(非同步),而這些非同步的行為要如何進行排序呢,即透過Event Queue。Event Queue專門用來執行非同步的函式,等整個主執行環境運行結束以後,才開始依序執行事件儲列裡面的函式,屬於「先進先出」的資料結構
setTimeout(function(){console.log('delay 0 sec')}, 0) 
console.log('Hello!')
因此上述程式碼可看成,Javacript 引擎執行到瀏覽器提供的setTimeout函式時並不會真的停下來,過0秒馬上執行console.log('delay 0 sec'),是在過0秒之後將此函數放到Event Queue,這就像一個待辦清單,裡面的程式不會馬上執行,要所有的全域執行環境與函式執行環境結束後,才會開始執行Event Queue的內容。那要如何知道主環境都已經執行完程式了呢,就是透過Event loop。Event loop可以看成一個無時無刻都在執行的程式,會不斷監聽程式是否全部執行完成,如果環境堆疊是空的,就會去檢查Event Queue是不是有函式待執行,並將Queue的函式移到Stack執行這些「待辦清單」

參考資源

  1. ALPHA Camp教材
  2. [筆記] 理解 JavaScript 中的事件循環、堆疊、佇列和併發模式(Learn event loop, stack, queue, and concurrency mode of JavaScript in depth) ~ PJCHENder<br>那些沒告訴你的小細節
  3. 從「為什麼不能用這個函式」談執行環境(runtime) - Huli
  4. JavaScript 原力覺醒 - 成為絕地武士之路 :: 第 11 屆 iThome 鐵人賽
  5. Understanding Event Loop, Call Stack, Event & Job Queue in Javascript | by Rahul Sagore | Medium
  6. 所以說event loop到底是什麼玩意兒?| Philip Roberts | JSConf EU - YouTube
2會員
15內容數
紀錄轉職路上的點點滴滴
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
Javascript入門-Day10:套件套件(Package)是將程式或程式庫進行組織、分發和共享的一種方式。在軟體開發中,套件通常包含了相關的程式碼、資源文件和元數據,並提供了統一的名稱空間和版本管理。
Thumbnail
avatar
浴火重生的雞
2024-06-04
Javascript入門-Day9:例外處理當你在開發程式時,難免會遇到各種錯誤和異常情況。這些錯誤可能是因為代碼中的錯誤、外部資源無法訪問或其他不可預期的狀況。為了提高程式的可靠性、穩定性和可維護性,我們使用「例外處理」來處理這些異常情況。
Thumbnail
avatar
浴火重生的雞
2024-06-03
Javascript入門-Day8:物件導向本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
Thumbnail
avatar
浴火重生的雞
2024-06-02
JavaScript 同步、非同步、Event loop 淺談 JavaScript 同步、非同步、Event Loop 的觀念
Thumbnail
avatar
蕭宇廷
2023-11-27
JavaScript 程式札記 : event 事件事件(event)就是網頁中發生的某些事情,例如當用戶點擊按鈕、移動滑鼠、輸入文字等,JavaScript 能夠偵測這些事件,並執行相對應的程式碼。
Thumbnail
avatar
梧笙
2023-08-29
JavaScript — var letJava script 中有其中兩種宣告分別是 var 跟 let var 結果: let 結果: ** let 是一種區塊的變數宣告像是 if else while for 即跳出區塊時就無法取得資料
avatar
John
2022-05-08
【JavaScript 簡史】什麼是 ES5、ES6?網頁開發與 ECMAScript 的小故事在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
Thumbnail
avatar
Vivian Yeh
2022-01-15
JavaScript async/await上篇介紹的promise chain的寫法,是已經比原本好維護了沒錯,但是可讀性似乎還是有點不足,其實還可以改成用async/await的寫法,如下: E 其中,async是非同步的意思,等於是把getData()這個function定義為非同步,因此從console可以看到,test是最先被pri
Thumbnail
avatar
Vic Lin
2021-09-13
【Javascript】行動電話格式驗證輸入畫面 為什麼要做驗證? 因為作為設計者,永遠不該預設使用者會乖乖照設計者的意思輸入。
Thumbnail
avatar
2021-05-30
JavaScript 變數宣告 var, let, const 比較JavaScript在ES6新增了let, const等宣告變數的方式,其中let, const是block scope的,而var則是function scope。
Thumbnail
avatar
Vic Lin
2019-10-12