EventLoop

作者: 漂泊的小蘑菇 | 来源:发表于2018-09-08 14:29 被阅读0次

    三个关键字:

    EventLoop: 事件循环
    MicroTask: 微任务
    MacroTask: 宏任务

    三个要点:

    1. js是单线程语言
    2. 任务队列
    3. EventLoop 是js的执行机制

    一 js为什么是单线程语言?

    js是单线程语言与它的用途相关,js是浏览器脚本语言,主要用于与用户的交互以及操作dom节点,所以要避免复杂的同步问题,这就决定了它必须是单线程的。比如:假如js是多线程的,一个线程在dom节点上添加内容,一个线程删除该dom节点,这时浏览器该怎么执行?

    二 任务队列

    2.1 同步任务和异步任务
    由于js是单线程的,所以就意味着任务需要排队执行,任务又分为同步任务和异步任务。

    同步任务:在主线程上排队执行的任务,只有前一个任务执行完才会执行下一个任务,如果前一个任务耗时长,后一个任务就会一直等待,容易造成阻塞。
    异步任务:最开始不进入主线程,而是进入任务队列中的任务,当主线程执行完毕,系统会去查看任务队列,然后决定执行哪个异步任务,异步任务的执行顺序就和EventLoop机制,即微任务和宏任务相关。
    

    异步执行的运行机制:

    1. 首先执行主线程上的代码,形成执行栈,遇到异步任务就将它放入任务队列中。
    2. 主线程执行完毕,系统会查看任务队列,某个任务可以执行时,就进入执行栈中开始执行。(如果有微任务就执行所有的微任务,没有微任务就执行下一个宏任务, 每个宏任务执行完都要清空所有的微任务)。

    2.2 异步任务之微任务与宏任务
    js是单线程的,所有的异步任务都被放入到任务队列当中,任务队列又分为两类:微任务和宏任务。
    微任务:

      process.nextTick(先于promise执行)
      promise
      Object.observe
      MutaionObserver
    

    宏任务:

      setTimeout
      setInterval
      setImmediate
      IO
      UI rerendering
    

    三 Event Loop

    主线程从任务队列中读取任务的过程是循环的,所以整个的运行机制被称为 Event Loop(事件循环)。
    例子:

    console.log('main1');
    process.nextTick(function() {
        console.log('process.nextTick1');
    });
    setTimeout(function() {
        console.log('setTimeout');
        process.nextTick(function() {
            console.log('process.nextTick2');
        });
    }, 0);
    new Promise(function(resolve, reject) {
        console.log('promise');
        resolve();
    }).then(function() {
        console.log('promise then');
    });
    console.log('main2');
    

    结果:

    1. 开始执行代码输出main1, process.nextTick放到执行栈末尾,setTimeout 放到宏任务,new promise 立即执行输出promise,then方法放到微任务,执行最后一句代码输出main2。
    2. 主线程执行完毕,开始清空微任务,执行process.nextTick输出process.nextTick1, 在执行then输出promise then。
    3. 执行下次event loop,执行setTimeout输出 setTimeout,里面的 process.nextTick放到当前执行栈末尾,当前宏任务执行完毕,执行微任务,输出process.nextTick2。

    四 node中的Event Loop

    Node的执行过程
    1. v8引擎解析js脚本
    2. 调用node API
    3. libuv库执行node api, 将不同的任务分给不同的线程执行,以异步的形式将结果返回给v8引擎
    4. v8引擎将结果返回给用户
    Node的EventLoop的过程

    Node的EventLoop由6个任务阶段组成,每个阶段都有自己的任务队列,每当进入某个阶段,都会从所属的队列中取出任务来执行,当队列为空或者被执行任务的数量达到系统的最大数量时,进入下一阶段。这六个阶段都执行完毕称为一轮循环。
    六个阶段具体而言:

    1. timers:执行setTimeout() 和 setInterval()中到期的callback。
    2. I/O callbacks:上一轮循环中有少数的I/Ocallback会被延迟到这一轮的这一阶段执行
    3. idle, prepare:仅内部使用,process.nextTick就属于这一类
    4. poll:最为重要的阶段,执行I/O callback,在适当的条件下会阻塞在这个阶段
    5. check:执行setImmediate()的callback
    6. close callbacks:执行close事件的callback,例如socket.on("close",func)


      Node的EventLoop.png

    参考文章:
    https://www.cnblogs.com/wuguanglin/p/EventLoop.html(Node的EventLoop机制讲的比较好)

    相关文章

      网友评论

          本文标题:EventLoop

          本文链接:https://www.haomeiwen.com/subject/rqykgftx.html