js事件循环机制(二)

前言

上一篇介绍了 事件循环 的基础, 这一篇主要介绍 macrotaskmicrotask

一、引入

    (function test() {
        setTimeout(function() {console.log(4)}, 0);
        new Promise(function executor(resolve) {
            console.log(1);
            for( var i=0 ; i<10000 ; i++ ) {
                i == 9999 && resolve();
            }
            console.log(2);
        }).then(function() {
            console.log(5);
        });
        console.log(3);
    })()

执行结果

    1
    2
    3
    5
    4

可以看看whatwg规范,大概可以用下面的事件执行模型来理解

二、event-loop 执行模型

  • 1.在 macrotask 队列中执行最早的那个 task ,然后移出

  • 2.执行 microtask 队列中所有可用的任务,然后移出

  • 3.执行下一个 macrotask 中的任务 (再跳到第2步)

三、macrotask microtask分类

macrotask: 整段script代码 setTimeout setInterval setImmediate I/O UI渲染

microtask: Promise process.nextTick Object.observe MutationObserver

按照上面的事件执行模型和事件分类,来理解一下上面的demo

    //伪代码
    var macrotasks = ['整段script代码'],
        microtasks = [];
    //一次事件循环
    while( macrotasks.length>0){
        macrotasks.shift();
        // 有些macrotask 可能会产生macrotask microtasks
        //  即 microtasks.push()
        //  如上面的 '整段代码' 产生一个macrotask -> setTimeout,又产生一个microtask -> Promise
        while(microtasks.length>0){
            microtasks.shift();
        }
    }

上面的demo执行过程如下:开始时 macrotask队列 有 ‘整段的script代码’,microtask队列无任务。
开始执行第一个 macrotask:

  • 1.发现 setTimeout ,执行 macrotasks.push("setTimeout")
  • 2.发现 Promise执行console.log(1),执行 microtasks.push('Promise')
    ,执行console.log(2)
  • 3.执行console.log(3);

至此 第一个 macrotask 处理完成,检查是否有 microtask,开始处理 microtask:

  • 1.执行console.log(5);

至此 microtask 处理完成,检查是否还有 macrotask,开始处理第二个 macrotask:

  • 1.执行 console.log(4)

四、参考文章

1.深入理解 JavaScript 事件循环(二)— task and microtask

2.深入浅出JavaScript事件循环机制(下)

3.理解 js 事件循环二 (macrotask 和 microtask)

4.whatwg规范

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容