由於 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')
會先執行。
會先執行 stack 內的 function,直到 stack 都執行完,才會執行 event loop,將 callback queue 內的 function 執行完。
console.log('Hello ');
console.log('Hello ')
進 stack
- 清空 stack,在 console 顯示
Hello
setTimeout(() => console.log('Sam'), 0);
setTimeout()
進 stack
- 清空 stack,執行 browser thread 的
timer(0)
timer(0)
時間一到,將callback
塞進 callback queue
console.log('World ');
console.log('World ')
進 stack
- 清空 stack,在 console 顯示
Hello World
- 所有 synchronous function 都已經執行完,開始執行 event loop
- 清空 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 ?