Javascript 事件迴圈(Event Loop)
阿新 • • 發佈:2019-01-11
規則:同一時間只有一個任務在執行,同時執行的過程不能被中途打斷
事件佇列型別:macrotask queue 和microtask queue
常見的macrotask 和 microtask 如下 :
macrotask queue :
Mouse Event
Keyboard Event
Network Event
HTML Parsing
setTimeout
setInterval
setImmediate
I/O
microtask queue :
DOM mutations
Promise
Object.observe
process .nextTick
從分類對應的事件處理來看,macrotask 處理的是耗時比較長的,而 microtask 處理是耗時短的。奇怪的是這兩個詞看起來比較像,一個是mac-rotask ,另一個是 mic-rotask 就只差了一個字母, 它們分別對應的單詞意思表達為:macrotask(表示巨集觀的)和microtask(表示微觀的)
示例如下 :
console.clear();
console.log('========== START ==========');
Part-1:
var interval = setInterval(() => console.log('setInterval'), 0)
setTimeout(()=>console.log('setTimeout 1'),0)
setTimeout(()=>console.log('setTimeout 2'),0)
Part-2:
setTimeout(() => {
console.log('setTimeout 3')
Promise.resolve()
.then(() => {
console.log('promise 1')
})
.then(() => {
console.log('promise 2')
})
.then(() => {
setTimeout(() => {
console.log('setTimeout 4')
Promise.resolve()
.then(() => {
console.log('promise 3')
})
.then(() => {
console.log('promise 4')
})
.then(() => {
setTimeout(() => {
console.log('setTimeout 5')
Promise.resolve()
.then(() => {
console.log('promise 5')
})
.then(() => {
console.log('promise 6')
})
.then(() => {
clearInterval(interval)
console.log('========== END ==========')
})
}, 10)
})
}, 0)
})
}, 0)
Part-3:
Promise.resolve()
.then(() => {
console.log('promise 7')
})
.then(() => {
console.log('promise 8')
})
console.log('========== CONTINUE ==========')
其邏輯結構如下:
=> START
Part-1:
setInterval
setTimeout
setTimeout
Part-2:
setTimeout
Promise => then
=> then
=> then
=> setTimeout
Promise => then
=> then
=> then
=> setTimeout
Promise => then
then
then
clearInterval
END
Part-3:
Promise => then
=> then
CONTINUE
結果顯示如下:
Console was cleared
EventLoop:3 ========== START ==========
EventLoop:60 ========== CONTINUE ==========
EventLoop:49 promise 7
EventLoop:52 promise 8
EventLoop:1 undefined
EventLoop:4 setInterval
EventLoop:9 setTimeout 3
EventLoop:12 promise 1
EventLoop:15 promise 2
2EventLoop:4 setInterval
EventLoop:19 setTimeout 4
EventLoop:22 promise 3
EventLoop:25 promise 4
3EventLoop:4 setInterval
EventLoop:29 setTimeout 5
EventLoop:32 promise 5
EventLoop:35 promise 6
EventLoop:39 ========== END ==========
EventLoop:6 setTimeout 2
EventLoop:5 setTimeout 1
那如果把Part-1移動到Part-3後面結果會是怎麼的呢?答案是,保持與上面一致執行過程是怎樣控制的?首先要理解上面提到的規則,其次記住事件佇列的分類(macrotask和microtask),同時還需要記住對應佇列下的事件型別。本文由:北大青鳥學校開發小組提供
- 在一個事件迴圈週期中一個任務的開始是從 macrotask 佇列開始執行的,當一個 macrotask 執行結束後,microtasks 佇列中的任務將一個個被執行,在 microtask 執行時還可以加入多個 microtask (事件巢狀處理),直到 microtask 佇列清空,然後又回到macrotask繼續迴圈。