浏览器事件环
js的script是同步代码,js引擎会先执行主栈代码,遇到诸如ajax、定时器等异步方法会先存放到宏任务队列中,遇到微任务方法则存放到微任务队列,等待宏任务执行完毕后,先清空微任务队列,微任务执行完毕进行GUI渲染页面,然后去查看宏任务队列是否还有没有完成的任务,如果存在,从队列中取出一个放到主栈执行,执行完之后,再去清空微任务,再去进行GUI渲染,再去查看宏任务队列,再取出任务循环这个过程执行
- 进程和线程,一个进程包含多个线程,进程是计算机分配任务的最小调度单位。线程是操作系统进行运算调度的最小单位,一个应用不止一个进程,比如浏览器的每一个页卡都是一个进程,保证互相之间独立。
为什么js是单线程执行
- js主线程是单线程,执行js代码的时候,默认是单线程在从上到下依次执行
- 浏览器在渲染页面的时候,会有一个渲染线程(浏览器内核)在工作,渲染线程在执行的时候,js引擎就会阻塞等待,js代码的执行和页面的渲染是互斥的。
- 如果js是多线程工作的,线程一要求新增一个dom,线程二要求删除一个dom,这个时候渲染线程就不知道怎么办
宏任务和微任务
- 宏任务,宿主环境提供的,比如浏览器
- 微任务,语言本身提供的,比如promise.then
- js在执行到ajax这种异步方法时,先不去执行,把它存放到宏任务队列中,在同步代码全部执行完毕后,再去执行
- 常见的宏任务:ajax、setTimeout、setIntervar、requestAnimationFrame、messageChannel、UI渲染、setImmediate(只在IE下才会执行)
- 常见的微任务:then、queueMicrotask(基于then)、mutationObserver(浏览器提供)
node事件环

什么是事件环
- node中处理非阻塞I/O的操作机制
- node启动后,就会初始化事件环
执行流程
- 先进行主栈代码的执行,注意主栈代码也属于宏任务,微任务是语言提供的
- 主栈代码执行后,会清空一次微任务队列,在清空微任务之前会先执行process.nextTick(优先级高于微任务,不属于事件环的一部分),然后会进入事件环执行
- node中的事件环包含以下几个阶段,timers、pending callbacks、idle,prepare、poll、close callbacks
- timers阶段,存放的是setTimeout、setInterval回调队列
- pending callbacks、close callbacks不受我们控制的,系统内部控制
- poll阶段,存放异步I/O操作队列
- check阶段,存放setImmediate队列
- 事件环的执行是从上到下依次执行的,如果主栈代码执行完毕后,这个时候timers中的队列为空,也就是定时器的等待时间还未到,会往下继续执行到poll阶段,查看异步队列是否有没有完成的任务吗,如果有就先处理poll中的队列,poll中的处理任务存在上限,最多当执行到99个的时候,会先退出poll阶段的执行,往下执行,如果poll阶段没有内容就执行check阶段的检查,如果check阶段队列存在任务,就执行,执行完毕后回到timers阶段继续事件环的执行,最终停在poll阶段阻塞等待
- 注意,上面的几个队列中存放的都是宏任务,每执行完一个宏任务,就清空一次微任务队列,在老的node版本中,当整个阶段的队列都执行完毕后才会去清空一次微任务队列。
process.nextTick作用
- 可以阻止立即从构造函数中触发事件,因为此时脚本还没有执行到为这个事件分配回调函数的地方
二者之间的关系
- node10版本之后的事件环和浏览器的事件环执行结果一样了,但是本质不一样


4011

被折叠的 条评论
为什么被折叠?



