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

相关文章
相关标签/搜索