js事件循環機制(Event Loop)


javascript從誕生之日起就是一門  單線程的  非阻塞的  腳本語言,單線程意味着,javascript代碼在執行的任何時候,都只有一個主線程來處理所有的任務,非阻塞靠的就是 event loop(事件循環),本文就講解下事件循環。

event loop它最主要是分三部分:主線程、宏隊列(macrotask)、微隊列(microtask)

js的任務隊列分為同步任務和異步任務,所有的同步任務都是在主線程里執行的,異步任務可能會在macrotask或者microtask里面

主線程

就是訪問到的script標簽里面包含的內容,或者是直接訪問某一個js文件的時候,里面的可以在當前作用域直接執行的所有內容(執行的方法,new出來的對象等

宏隊列(macrotask)

setTimeout、setInterval、setImmediate、I/O、UI rendering

微隊列(microtask)

promise.then、process.nextTick

執行順序

1、先執行主線程

2、遇到宏隊列(macrotask)放到宏隊列(macrotask)

3、遇到微隊列(microtask)放到微隊列(microtask)

4、主線程執行完畢

5、執行微隊列(microtask),微隊列(microtask)執行完畢

6、執行一次宏隊列(macrotask)中的一個任務,執行完畢

7、執行微隊列(microtask),執行完畢

8、依次循環。。。

 看下面代碼練習練習

console.log(1)
process.nextTick(() => {
  console.log(8)
  setTimeout(() => {
    console.log(9)
  })
})
setTimeout(() => {
  console.log(2)
  new Promise(() => {
    console.log(11)
  })
})
requestIdleCallback(() => {
  console.log(7)
})
// 特殊說明: new Promise()屬於主線程任務 let promise = new Promise((resolve,reject) => { setTimeout(() => { console.log(10) }) resolve()
// 這個console也屬於主線程任務 console.log(4) }) fn() console.log(3) promise.then(() => { console.log(12) }) function fn(){ console.log(6) }

結果是1、4、6、3、12、8、2、11、10、9、7

這個寫法可以囊括80%以上的event loop循環機制的場景了,下面開始梳理具體的運行機制。

js是從上到下執行的,所以上來先打印的是 1 ,繼續往下走;

遇見了process.nextTick,因為它屬於微隊列(microtask),並且當前主線程的代碼還沒有執行完畢,所以它被展示扔到了微隊列里,暫時不打印;

這個時候又遇到了setTimeout,setTimeout是屬於宏隊列(macrotask);

requestIdleCallback,這里也是不立即執行的,它也不屬於任何隊列,這里不做詳細解釋;

promise在實例化的時候,這里的setTimeout繼續被丟到了宏隊列(macrotask)中,並執行了成功的方法,在有promise.then的調用的時候就會去出發,但這里不做打印,接着發現了console,這里直接打印 4 );

fn函數直接調用,直接打印 6

console,直接打印 3

promise.then因為它屬於微隊列,但是它在promise實例化的時候被調用了,所以它會在微隊列的最前面執行;

到這里主線程里面就沒有任何可以執行到東西了,下面開始走微隊列(microtask):

由於promise.then被提前調用了,所以它會先執行,打印 12

微隊列(microtask)里面還有一個,就是上面的process.nextTick,執行它,打印 8 ,這個時候發現它有一個setTimeout,放到宏隊列(macrotask);

到這里微隊列就走完了,下面開始走宏隊列(macrotask):

最外面的setTimeout在一開始的時候被放了進去,所以先執行它,打印 2 ,發現它里面有promise被實例化,直接執行,打印 11

下一個要走的就是promise里面的setTimeout,打印 10

還剩最后一個setTimeout,就是process.nextTick里面的,打印 9

到這里主線程、宏隊列(macrotask)、微隊列(microtask)就全都跑完了,在全部跑完的時候,requestIdleCallback才會執行,打印 7

requesIdleCallback會在當前瀏覽器空閑時期去依次執行,在整個過程當中你可能添加了多個requestIdleCallback,但是都不會執行,只會在空閑時期,去依次根據調用的順序就執行。

 


免責聲明!

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



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