How does Event Loop work?


Posted by Christy on 2021-10-10

This is the note about this video What the heck is the event loop anyway? | Philip Roberts | JSConf EU, and here is the Transcript

The topic here is to know how JavaScript event loop works in browser

source: CodePen Home Event Loop

With the runtime V8

02'50"

So if we look at the JavaScript Runtime itself like V8 which is the Runtime inside Chrome. This is a simplified view of what JavaScript Runtime is. The heap, where memory allocation happens, and then there's the call stack, which is where your stack frames are and all that kind of stuff

在 Chrome 瀏覽器的環境 V8 裡面,有 Heap 跟 call stack。

How does a call stack run?

if we step into a function, we put something on to the stack, if we return from a function, we pop off the top of the stack that's all the stack can do...

04'37" - 06'03": the call stack ->
one thread == one call stack == one thing at a time

function multiply(a, b) {
  return a * b;
}

function square(n) {
  return multiply(n, n);
}

function printSquare(n) {
  var squared = square(n);
  console.log(squared);
}

printSquare(4);

In the stack, there's a function main() to run first, then the next stack goes upon main() which is printSquare(4), so the sequence from bottom to top in the stack would be like below:

main() -> printSquare(4) -> square(n) -> multiply(n, n)

And then it popped off of the stack while it finished its work.

Blocking and solution

Blocking: What happens when things are slow?

Solutions: asynchronous callbacks

Concurrency & the Event Loop

The reason we can do things concurrently is that the browser is more than just the Runtime.

11'50": How does JavaScript actually work in the browser?

So, same as before, run code, console log hi, logs hi to the console, simple. now we can see what happens when we call setTimeout. We are ‑‑ we pass this callback function and a delay to the setTimeout call. Now setTimeout is an API provided to us by the browser, it doesn't live in the V8 source, it's extra stuff we get in that we're running the JavaScript run time in. The browser kicks off a timer for you. And now it's going to handle the count down for you, right, so that means our setTimeout call, itself is now complete, so we can pop off the stack. “JSConfEU”, clear...

17'35": setTimeout is not accurate

like what time out is actually doing, it's not a guaranteed time to execution, it's a minimum time to execution, just like setTimeout zero doesn't run the code immediately it runs the code next‑ish, sometime

20'17": callbacks

Below is the code from this video.

  1. we run forEach function first and print 1 => 2 => 3 => 4

  2. Secondly, run asyncForEach function and go to array.forEach function

  3. trigger setTimeout, Web Apis push the cb to queue

  4. event loop check the call stack and put cb into stack and execute

// Synchronous
[1, 2, 3, 4].forEach(function (i) {
  console.log(i);
})

// Asynchronous
function asyncForEach(array, cb) {
  array.forEach(function () {
    setTimeout(cb, 0);
  })
}

asyncForEach([1, 2, 3, 4], function (i) {
  console.log(i);
})

Imgur

source: callbacks online watch

22'18" rendering:

the browser would like to repaint the screen every 16.6 milliseconds, 60 frame a second is ideal, that's the fastest it will do repaints if it can. But it's constrained by what you're doing in JavaScript for various reasons, so it can't actually do a render if there is code on the stack, right. Like the render kind of call is almost like a callback in itself. It has to wait till the stack is clear.

Browser can't do anything while running the synchronous fn, but after queueing it up asynchronously and we do the render.

// synchronous
[1, 2, 3, 4].forEach(function (i) {
  console.log('processing sync');
  delay();
})

// Asynchronous
function asyncForEach(array, cb) {
  array.forEach(function () {
    setTimeout(cb, 0);
  })
}

asyncForEach([1, 2, 3, 4], function (i) {
  console.log('processing async', i);
  delay();
})

Imgur

source: rendering online watch


Here's also supplementary information from this article JavaScript 中的同步與非同步(上):先成為 callback 大師吧!

  1. JavaScript 可以在兩種環境中執行,而每個環境會有不同的東西可以用,例如 DOM 物件是瀏覽器給的;而 Node.js 有提供一個讀寫檔案的介面叫 file system fs

  2. setTimeout 在兩個環境中都有。

  3. Blocking vs Non-blocking: 阻塞代表程式會卡在某一行;非阻塞執行結果會放在回呼函式裡面,因此不會卡住。

  4. Synchronous vs Asynchronous:

    Node.js 官方文件也可以看到阻塞 vs 非阻塞的範例

    Blocking methods execute synchronously and non-blocking methods execute asynchronously.

    這裡比較不直覺的地方是,中文裡面的「同步」、「非同步」,直覺上來說是相反的。

    同步在這裡真正的意思是,等到事情做完了才進到下一步,所有東西綁在一起,不能分開執行。

    非同步是說,可以多件事情分頭進行,不用綁在一起。

  5. 因此在 JavaScript 裡面:

    Synchronous = Blocking

    Asynchronous = Non-blocking

    source: Overview of Blocking vs Non-Blocking

    要特別注意的是,如果是在別的地方討論阻塞非阻塞以及同步非同步,例如系統 I/O,那意思就會不一樣了。

  6. cb 函式傳進去的參數是另外一個函式,而不是把執行函式傳進去

    fn 是一個 function,fn() 是執行 function

  7. cb 第一個參數通常是錯誤訊息

  8. 最上面的經典影片理解 Event Loop 運作方式

  9. setTimeout 執行時間不精準,比如說時間放零,不一定就會立刻執行,有可能更久。

    source: MDN: Reasons for delays longer than specified

  10. event loop 的 callback queue 還區分成 macro task 跟 micro task 兩種

  11. Node.js 跟瀏覽器的 event loop 背後的原理是不同的,也就是說,我看的影片只說了瀏覽器的原理,我還沒學到 Node.js 的版本。這裡之後再回來理解!

  12. 瀏覽器裡面還有 Web Worker 可以執行 JavaScript,不只是 main thread 而已。

  13. 非同步小測驗:

    a. 這段程式碼的問題是,執行時會一直等到 getAPIResponse 有收到結果以後,才會往下執行,因此沒有做出「判斷活動是否已經開始」這件事。

    b. cb 函式裡面通常會需要傳兩個參數,第一個是錯誤訊息,第二個是收到的資料,這樣寫會沒辦法拿到資料。

    c. 有可能,因為 setTimeout 的計時並不準確,因此會先執行下面其他的程式碼,等到 call stack 為空時,才會執行到 setTimeout

    d. 這題我不知道...

好像有點似懂非懂?先記著,之後要回來複習。










Related Posts

認知機器人研究資源整理

認知機器人研究資源整理

[ 紀錄 ] 實戰練習 - 抽獎程式 (以 Express 實作後端 API )

[ 紀錄 ] 實戰練習 - 抽獎程式 (以 Express 實作後端 API )

[T-SQL] MSSQL 根據已有的表創建新表

[T-SQL] MSSQL 根據已有的表創建新表


Comments