Js與Nodejs的event-loop的執行機制

我就是近視怎麼了發表於2018-03-27

js是單執行緒

javascript在最初設計時設計成了單執行緒,為什麼不是多執行緒呢?如果多個執行緒同時操作DOM豈不會很混亂?比如,假定JavaScript同時有兩個執行緒,一 個執行緒在某個DOM節點上新增內容,另一個執行緒刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?這裡所謂的單執行緒指的是主執行緒是單執行緒的,所以在Node 中主執行緒依舊是單執行緒的。

瀏覽器的event-loop

執行棧與任務佇列

(1)所有同步任務都在主執行緒上執行,形成一個執行棧。
(2)主執行緒之外,還存在一個"任務佇列"(task queue)。只要非同步任務有了執行結果,就在"任務佇列"之中放置
    一個事件。 
(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務佇列",看看裡面有哪些事件。那些對應的非同步
    任務,於是結束等待狀態,進入執行棧  
    ,開始執行。 
(4)主執行緒不斷重複上面的第三步。
複製程式碼

Js與Nodejs的event-loop的執行機制

  • 任務佇列分為macro-task(巨集任務)和micro-task(微任務)。

  • macro-task(巨集任務): setTimeout, setInterval, setImmediate, I/O等

  • micro-task(微任務): process.nextTick, 原生Promise(有些實現的promise將then方法放到了巨集任務中),Object.observe(已廢棄), MutationObserver等


  • console.log(1);
    console.log(2);
    Promise.resolve().then(function(){
        console.log('promise')
    });
    setTimeout(function(){
        console.log('setTimeout1')
        Promise.resolve().then(function(){
            console.log('promise')
        });
    })
    setTimeout(function(){
        console.log('setTimeout2');
    });
    
    複製程式碼

    結果:
    1
    2
    promise
    setTimeout1
    promise
    setTimeout2
    
    瀏覽器 會先執行同步程式碼 ===> 然後檢視任務佇列 ===> 先執行micro-task(微任務) ===> 在執行macro-task(巨集任務)
    個人理解: 有微先走微,沒微就走巨集。複製程式碼

    Nodejs的event-loop

    Nodejs與瀏覽器的 event-loop有些不同

    nodeJS中的巨集任務和微任務在瀏覽器的基礎上有新增了幾個
    微任務
    then
    nextTick
    messageChannel
    mutationObersve

    巨集任務
    setTimeout
    setInterval
    setImmediate

    nodejs的event-loop圖解

    Js與Nodejs的event-loop的執行機制

    當node執行完同步程式碼時就會執行上圖的順序

    console.log(1);
    console.log(2);
    Promise.resolve().then(function(){
        console.log('promise')
    });
    setTimeout(function(){
        console.log('setTimeout1')
        Promise.resolve().then(function(){
            console.log('promise')
        });
    })
    setTimeout(function(){
        console.log('setTimeout2');
    });
    複製程式碼

    node環境裡的執行順序

    1
    2
    promise
    setTimeout1
    setTimeout2
    promise
    node 執行完同步程式碼 之後會先查詢 微任務佇列 然後逐一清空 微任務 然後走timer 清空timer(巨集任務)複製程式碼


    node裡的的 nextTick 與 setImmediate

    process.nextTick(function(){    console.log('nextTick')});setImmediate(function(){    console.log('immediate')});
    
    nextTickimmediate因為 nextTick是微任務 所以nextTick先執行複製程式碼


    相關文章