zoukankan      html  css  js  c++  java
  • JavaScript中的异步 macrotask 和 microtask

      看过很多setTimeout、Promise执行顺序的面试题,一直不明白为啥都是异步操作,Promise就牛×些呢?直到了解了macrotask和micromask才恍然大悟...

      先来一道面试题助助兴:

    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和Microtasks

    Macrotasks和Microtasks 都属于上述的异步任务中的一种,他们分别有如下API:

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

    microtasks: process.nextTick, Promise, MutationObserver

      

    异步任务队列分为 macrotasks 和 microtasks, 在每一次事件循环中,macrotask只会提取一个执行,而microtask会一直提取,直到microsoft队列为空为止。也就是说如果某个microtask任务被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止(microtasks优于macrotasks执行)。而事件循环每次只会入栈一个macrotask,主线程执行完成该任务后又会检查microtasks队列并完成里面的所有任务后再执行macrotask的任务。

    弄清楚了这条规则后,再来分析上面的面试题就小菜一碟了。 

    参考文章:

    https://juejin.im/post/5bac87b6f265da0a906f78d8

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

  • 相关阅读:
    react条件渲染
    js用replaceAll全部替换的方法
    批量重命名图片,去除括号
    [转]自定义alert弹框,title不显示域名
    [转]ASCII码表及扩展ASCII码表,方便查阅
    [转]PHP中file_put_contents追加和换行
    Response
    Redirect
    Request
    Paginator
  • 原文地址:https://www.cnblogs.com/chenwenhao/p/9751112.html
Copyright © 2011-2022 走看看