EventLoop

三个关键字:

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)