簡單總結下JS中EventLoop事件循環機制


最近看了很多關於JS中事件循環機制的介紹,很多大佬寫的都非常的詳細,在此簡單記錄下我個人的理解,以下是個人見解,如果有錯誤,你來打。。。不是,希望指正。

Event Loop 是什么

JavaScript的事件分兩種,宏任務(macro-task)微任務(micro-task)

  • 宏任務:包括整體代碼script,setTimeout,setInterval

  • 微任務:Promise.then(非new Promise),process.nextTick(node中)

  • 事件的執行順序,是先執行宏任務,然后執行微任務,這個是基礎,任務可以有同步任務和異步任務,同步的進入主線程,異步的進入Event Table並注冊函數,異步事件完成后,會將回調函數放入Event Queue中(宏任務和微任務是不同的Event Queue),同步任務執行完成后,會從Event Queue中讀取事件放入主線程執行,回調函數中可能還會包含不同的任務,因此會循環執行上述操作。

setTimeout(() => {
    console.log('延時1秒');
},1000)
console.log("開始")
輸出:
開始
延時1秒

上述代碼,setTimeout函數是宏任務,且是異步任務,因此會將函數放入Event Table並注冊函數,經過指定時間后,把要執行的任務加入到Event Queue中,等待同步任務console.log("開始")執行結束后,讀取Event Queue中setTimeout的回調函數執行。

上述代碼不包含微任務,接下來看包含微任務的代碼:

setTimeout(function() {
    console.log('setTimeout');
},1000)

new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})

console.log('console');
  • 首先setTimeout,放入Event Table中,1秒后將回調函數放入宏任務的Event Queue中
  • new Promise 同步代碼,立即執行console.log('promise'),然后看到微任務then,因此將其放入微任務的Event Queue中
  • 接下來執行同步代碼console.log('console')
  • 主線程的宏任務,已經執行完畢,接下來要執行微任務,因此會執行Promise.then,到此,第一輪事件循環執行完畢
  • 第二輪事件循環開始,先執行宏任務,即setTimeout的回調函數,然后查找是否有微任務,沒有,時間循環結束

到此做個總結,事件循環,先執行宏任務,其中同步任務立即執行,異步任務,加載到對應的的Event Queue中(setTimeout等加入宏任務的Event Queue,Promise.then加入微任務的Event Queue),所有同步宏任務執行完畢后,如果發現微任務的Event Queue中有未執行的任務,會先執行其中的任務,這樣算是完成了一次事件循環。接下來查看宏任務的Event Queue中是否有未執行的任務,有的話,就開始第二輪事件循環,依此類推。

上述例子只是簡單的一層嵌套,接下來看一個稍微復雜了一點點的例子:

console.log('1');
setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
輸出:
1
2
4
3
5
  • 宏任務同步代碼console.log('1'),不多說
  • setTimeout,加入宏任務Event Queue,沒有發現微任務,第一輪事件循環走完
  • 第二輪事件循環開始,先執行宏任務,從宏任務Event Queue中獨取出setTimeout的回調函數
  • 同步代碼console.log('2'),發現process.nextTick,加入微任務Event Queue
  • new Promise,同步執行console.log('4'),發現then,加入微任務Event Queue
  • 宏任務執行完畢,接下來執行微任務,先執行process.nextTick,然后執行Promise.then
  • 微任務執行完畢,第二輪事件循環走完,沒有發現宏任務,事件循環結束

以上就是看完一些介紹的文章后的一點個人理解,大量參考了掘金一位大佬ssssyoki的文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM