• JavaScript event loop事件循环 macrotask与microtask


    macrotask  姑且称为宏任务,在很多上下文也被简称为task。例如:

     setTimeout,

    setInterval,

    setImmediate,

    I/O,

    UI rendering.

    microtask 微任务,也称job。例如:


    process.nextTick,

    Promise(原生),

    Object.observe,

    MutationObserver

    备注:同时需要注意的是,在 ES 当中称 microtask 为 “jobs”。比如 ES6标准 8.4节当中的 “EnqueueJob” 意思指添加一个 microtask。

    看看下面的实例:

    setImmediate(function(){
        console.log(1);
    },0);
    setTimeout(function(){
        console.log(2);
    },0);
    new Promise(function(resolve){
        console.log(3);
        resolve();
        console.log(4);
    }).then(function(){
        console.log(5);
    });
    console.log(6);
    process.nextTick(function(){
        console.log(7);
    });
    console.log(8);
     
    //输出结果是3 4 6 8 7 5 2 1

    看看另一题目

    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');
    

      

    1、首先 setTimeout A 被加入到事件队列中  ==>  此时macrotasks中有[‘A’];

    2、obj.func()执行时,setTimeout B 被加入到事件队列中  ==> 此时macrotasks中有[‘A’,‘B’];

    3、接着return一个Promise对象,Promise 新建后立即执行 执行console.log('C'); 控制台首次打印‘C’;

    4、然后,then方法指定的回调函数,被加入到microtasks队列,将在当前脚本所有同步任务执行完才会执行。 ==> 此时microtasks中有[‘D’];

    5、然后继续执行当前脚本的同步任务,故控制台第二次输出‘E’;

    6、此时所有同步任务执行完毕,如上所述先检查microtasks队列完成其中所有任务,故控制台第三次输出‘D’;

    7、最后再执行macrotask的任务,并且按照入队列的时间顺序,控制台第四次输出‘A’,控制台第五次输出‘B’。


    结果 C  E  D A B
    setTimeout(function timeout () {
          console.log('timeout');
        },0);
    
        setImmediate(function immediate () {
          console.log('immediate');
        });
    

    结果 

    immediate
     timeout

    setInterval(function timeout () {
          console.log('setInterval');
        },0);
                
                setTimeout(function timeout () {
          console.log('timeout');
        },0);
    
        setImmediate(function immediate () {
          console.log('immediate');
        });

    结果:

    immediate
     setInterval
     timeout
     setInterval  

     

    setTimeout(function timeout () {
          console.log('timeout');
        },0);setInterval(function timeout () {
          console.log('setInterval');
        },0);
    

      

    timeout
    setInterval

    另一个

    setTimeout(function timeout () {
      console.log('timeout');
    },0);
    
    setImmediate(function immediate () {
      console.log('immediate');
    });
    
    process.nextTick(function immediate () {
      console.log('nickTick');
    });
    

    结果

    nextTick
    timeout
    immediate

    process.nextTick像是一个插入的tick. 生成了一个新的周期. 说白了, 是一个插队行为.

    关于micro-task和macro-task的执行顺序,可看下面这个例子(来自《深入浅出Node.js》):
    //加入两个nextTick的回调函数
    process.nextTick(function () {
        console.log('nextTick延迟执行1');
    });
    process.nextTick(function () { 
        console.log('nextTick延迟执行2');
    });
    // 加入两个setImmediate()的回调函数
    setImmediate(function () {
        console.log('setImmediate延迟执行1'); 
        // 进入下次循环 
        process.nextTick(function () {
            console.log('强势插入');
        });
    });
    setImmediate(function () {
        console.log('setImmediate延迟执行2'); 
    });
     
    console.log('正常执行')

    书中给出的执行结果是:

    正常执行
    nextTick延迟执行1
    nextTick延迟执行2
    setImmediate延迟执行1
    强势插入
    setImmediate延迟执行2

    process.nextTick在两个setImmediate之间强行插入了。
    但运行这段代码发现结果却是这样:

    正常执行
    nextTick延迟执行1
    nextTick延迟执行2
    setImmediate延迟执行1
    setImmediate延迟执行2
    强势插入
    

    朴老师写那本书的时候,node最新版本为0.10.13,而我的版本是6.x  

     
  • 相关阅读:
    slf4j + log4j 记录日志
    Executors介绍
    Java集合(JDK1.6.0_45)
    Java多线程系列目录(共43篇)
    线程池体系
    FutureTask
    23种设计模式分类
    结构型 之 适配器模式
    信号量Semaphore详解以及应用
    Excel格式转化工具
  • 原文地址:https://www.cnblogs.com/surfaces/p/10736151.html
Copyright © 2020-2023  润新知