點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Event Loop Model 執行 Asynchronous Function

Sam Xiao's Avatar 2019-08-26

由於 ECMAScript 是 Single Thread 語言,對於繁重的運算動作,就無法使用 Multi Thread 解決,因此 Asynchronous 在 ECMAScript 格外重要。Browser 使用獨特的 Event Loop Model 實現 Asynchronous,要能徹底了解其背後運作原理,才能掌握 ECMAScript 的 Asynchronous Function。

Version

ECMAScript 5

Single Thread

  • One call stack
  • One thing at a time

ECMAScript 最大的特色就是 runtime 為 single thread,也就是只有一個 call stack,因此一個時間只能做一件事情。

也由於只有一個 thread,只要遇到 大量運算,ECMAScript 就會停住等待,無法令開 thread 處理,因此使用者體驗就會不好。

因此 browser 做了擴充,有些東西並不是由 runtime 實作,而是由 browser 提供:

  • DOM
  • AJAX (XMLHttpRequest)
  • setTimout()

這三類由 browser 所提供的 API,屬於 asynchronous 部分。

Event Loop Model

console.log('Hello ');
setTimeout(() => console.log('Sam'), 0);
console.log('World ');
// Hello World Sam

setTimeout()0 秒時,會先執行 console.log('Sam') 還是 console.log('World ') ?

既然 dealy 0 秒,且寫在前面,應該先執行吧 ?

concole.log('Hello ');
$.get('url', data => console.log(data)); // { name: 'Sam' }
console.log(' World');
// Hello World { name: 'Sam' }

當使用 AJAX 時,也會發現 console.log(' World') 會先執行。

eventloop000

會先執行 stack 內的 function,直到 stack 都執行完,才會執行 event loop,將 callback queue 內的 function 執行完。

console.log('Hello ');

loop001

  • console.log('Hello ') 進 stack

loop002

  • 清空 stack,在 console 顯示 Hello
setTimeout(() => console.log('Sam'), 0);

loop003

  • setTimeout() 進 stack

loop004

  • 清空 stack,執行 browser thread 的 timer(0)

loop005

  • timer(0) 時間一到,將 callback 塞進 callback queue
console.log('World ');

loop006

  • console.log('World ') 進 stack

loop007

  • 清空 stack,在 console 顯示 Hello World

loop008

  • 所有 synchronous function 都已經執行完,開始執行 event loop

loop009

  • 清空 callback queue,在 console 顯示 Hello World Sam

Conclusion

  • Asynchronous function 會將 callback 先塞進 callback queue,不會立即執行
  • 等所有 synchronous function 都執行完,才開始執行 event loop 清空 callback queue 執行 asynchronous function

Reference

Philp Robers : What the heck is the event loop anyway ?