JavaScript 事件循環是一種處理異步任務的執行機制,通過將任務添加到事件隊列中,實現在單線程 JavaScript 引擎中高效處理異步編程。
通常,JavaScript 的執行過程是單線程同步進行的,只有當某個任務被執行完畢后,才會開始執行下一個任務。但是在某些情況下,某些任務需要異步執行,比如在網頁上加載遠程數據或者執行動畫效果時,這些任務不能夠阻塞整個程序的執行。事件循環機制就是為了解決這個問題而產生的。
在 JavaScript 中,異步任務也稱為宏任務(macrotask),同步任務稱為微任務(microtask),二者的執行順序非常重要,決定了 JavaScript 的執行結果。異步任務被添加到事件隊列中,等待執行;微任務被添加到微任務隊列中,等待主線程空閑時執行。
// 添加一個宏任務
setTimeout(() => {
console.log('Hello world!');
}, 0);
// 添加一個微任務
Promise.resolve().then(() => {
console.log('Microtask executed!');
});
以上代碼會輸出 "Microtask executed!" 和 "Hello world!"。因為在 JavaScript 的事件循環中,微任務先于宏任務執行。
事件循環是通過不斷地循環檢查事件隊列和微任務隊列來判斷任務是否已經完成,以此來觸發回調函數的執行。當主線程執行完所有任務后,就會去檢查微任務隊列,將所有微任務逐個執行完畢后,再去處理宏任務隊列中的任務。
setTimeout(() => {
console.log('Task 1 executed!');
}, 0);
setTimeout(() => {
console.log('Task 2 executed!');
Promise.resolve().then(() => {
console.log('Microtask 2-1 executed!');
});
}, 0);
Promise.resolve().then(() => {
console.log('Microtask 1-1 executed!');
}).then(() => {
console.log('Microtask 1-2 executed!');
});
console.log('Task Synchronous executed!');
setTimeout(() => {
console.log('Task 3 executed!');
Promise.resolve().then(() => {
console.log('Microtask 3-1 executed!');
}).then(() => {
console.log('Microtask 3-2 executed!');
});
}, 0);
在上面的例子中,所有任務的執行順序如下:
- 同步任務 ->添加宏任務 ->添加宏任務 ->添加微任務 ->添加宏任務
- Task Synchronous executed!
- Microtask 1-1 executed!
- Microtask 1-2 executed!
- Task 1 executed!
- Task 2 executed!
- Microtask 2-1 executed!
- Task 3 executed!
- Microtask 3-1 executed!
- Microtask 3-2 executed!
通過以上例子可以看到,在事件循環中,微任務先于宏任務執行,而在宏任務隊列中,任務的執行順序是按照添加的順序進行,但是在微任務隊列中,微任務的執行順序可以被修改。
總的來說,JavaScript 事件循環是一個非常重要的概念,它可以幫助我們編寫高效的異步代碼,并且避免出現死鎖和阻塞等問題。了解事件循環的工作原理,可以幫助我們更好地掌握 JavaScript 的異步編程技術。