EventLoop

毋庸置疑,你们都很了解js是一门单线程语言,这也就说明JS没法进行多线程,可是JS中异步的功能彻底能够模拟多线程,并且效果还杠杠滴。固然,若是想彻底理解异步,首先要了解JS的运行核心——事件环(Event Loop),下面分两部分理解事件环:node

一:浏览器中的事件环(Event Loop)

  1. 为了能更好的理解JS在浏览器中的任务队列和事件循环,请看下图:

  • eventLoop 是由JS的宿主环境(浏览器)来实现的;
  • 事件循环能够简单的描述为如下四个步骤:
1. 函数入栈,当Stack中执行到异步任务的时候,就将他丢给WebAPIs,接着执行同步任务,直到Stack为空;
2. 此期间WebAPIs完成这个事件,把回调函数放入队列中等待执行(微任务放到微任务队列,宏任务放到宏任务队列)
3. 执行栈为空时,Event Loop把微任务队列执行清空;
4. 微任务队列清空后,进入宏任务队列,取队列的第一项任务放入Stack(栈)中执行,回到第1步。

复制代码
  1. 认识浏览器中的任务源(task):
  • 微任务:then 、messageChannel 、mutationObersve
  • 宏任务:setTimeout、setInterval、setTmmediate(只兼容ie)
  1. 下面实现一个小例子:
console.log(1);
console.log(2);
setTimeout(function () {
  console.log('setTimeout1');
  Promise.resolve().then(function () {
    console.log('promise');
  });
});
setTimeout(function () {
  console.log('setTimeout2');
});

复制代码

打印结果:promise

1
2
setTimeout1浏览器

promisebash

setTimeout2多线程

二:Node 环境中的事件环(Event Loop)

  1. 为了能更好的理解JS在Node环境中的任务队列和事件循环,请看下图:

  • 图虽然有些乱,可是咱们只需关心timers计时器阶段和poll轮询阶段,check检查阶段便可,clons关闭阶段以及微任务队列便可。异步

  • Node 环境中微任务是插缝执行,(若是执行宏任务的时候发现了微任务, 不会像浏览器同样执行了,而是将为微任务放到微任务队列中,等待整个宏 任务队列执行完毕或者达到执行上线后,下一个阶段开始的时候先执行 完微任务队列中的任务)。函数

  1. 认识Node中的任务源(task):
  • 微任务: then 、nextTick 、 messageChannel 、mutationObersve
  • 宏任务:setTimeout 、setInterval 、setImmediate 、io文件操做
  1. 例一:timeout、immediate 两个谁先执行不必定 取决于node的执行时间。
setTimeout(function () {
    console.log('setTimeout1');
})
setImmediate(function () {
    console.log('setImmediate2');
});
复制代码
打印结果有两种:
  • 1) setTimeout1 setImmediate2
  • 2) setImmediate2 setTimeout1
  1. 例二: 若是i/o文件操做之后就会先执行setImmediate,由于setImmediate在i/o文件操做后面的那个阶段执行,执行完setImmediate会在下一个阶段的时候再执行setTimeout (timers 计时器执行阶段)
let fs = require('fs');
fs.readFile('1.log', function () {
  console.log('fs');
  setTimeout(function () {
    console.log('timeout');
  });
  setImmediate(function () {
    console.log('mmiediate');
  });
});

复制代码
打印顺序结果
  • fs 、 miediate、 timeout
  1. 例三: 微任务中nextTIck 会比then先执行。
Promise.resolve().then(function () {
  console.log('then2'):
});
process.nextTick(function () {
  console.log('nextTick1');
});


复制代码
打印顺序结果
  • nextTick1 then2
  1. 例四: 微任务会优先与i\o文件操做执行。
let fs = require('fs');
fs.readFile('./1/log',function(){
    console.log('fs')
})
process.nextTick(function(){
    console.log('text2');
})

复制代码
打印执行结果
  • text2 fs

好了,今天就到这,若有错误,请下方留言。做为码农一枚,最大的愿望和最伟大的理想是,大宝每天见,bug死生不复相见,相忘于江湖,恩怨一笔消失!!!oop

相关文章
相关标签/搜索