JavaScript中的異步 macrotask 和 microtask

  看過不少setTimeout、Promise執行順序的面試題,一直不明白爲啥都是異步操做,Promise就牛×些呢?直到了解了macrotask和micromask才恍然大悟...web

  先來一道面試題助助興:面試

setTimeout(()=>{
    console.log('A');
},0);
var obj={
    func: function () {
        setTimeout(function () {
            console.log('B')
        },0);
        return new Promise(function (resolve) {
            console.log('C');
            resolve();
        })
    }
};
obj.func().then(function () {
    console.log('D')
});
console.log('E');

// 結果:C、E、D、A、B

 咱們都知道JavaScript是一門單線程的語言,這也就意味着 JS 沒法進行多線程編程,可是 JS 當中卻有着無處不在的異步概念 。要徹底理解異步,就須要瞭解 JS 的運行核心——事件隊列(Event Loop)。實際上JS代碼執行都處於事件循環裏。事件循環發現有異步事件發生,就把這個任務放到事件隊伍中。編程

 

事件隊列是一個存儲着待執行任務的隊列,直白點說就是:咱們把每一次的異步操做(setTimeout、onclick、oninput事件、Promise...)當作一個異步任務,每進行一次異步操做,就把這個異步任務放入到異步事件的隊列中,直到主線程任務執行完畢,而後開始異步的事件隊列裏的任務按順序執行。多線程

 

Macrotasks和Microtasksapp

 

Macrotasks和Microtasks 都屬於上述的異步任務中的一種,他們分別有以下API:異步

macrotasks: setTimeout, setInterval, setImmediate, I/O, UI renderingoop

microtasks: process.nextTick, Promise, MutationObserverpost

  

異步任務隊列分爲 macrotasks 和 microtasks, 在每一次事件循環中,macrotask只會提取一個執行,而microtask會一直提取,直到microsoft隊列爲空爲止。也就是說若是某個microtask任務被推入到執行中,那麼當主線程任務執行完成後,會循環調用該隊列任務中的下一個任務來執行,直到該任務隊列到最後一個任務爲止(microtasks優於macrotasks執行)。而事件循環每次只會入棧一個macrotask,主線程執行完成該任務後又會檢查microtasks隊列並完成裏面的全部任務後再執行macrotask的任務。ui

 

弄清楚了這條規則後,再來分析上面的面試題就小菜一碟了。 spa

 

參考文章:

http://www.javashuo.com/article/p-akdhbawz-br.html

http://ju.outofmemory.cn/entry/349456

相關文章
相關標籤/搜索