我不知道的 Event Loop,对,我不知道!!

gg.gif

EventLoop是MS中的高频问题,理解繁琐,一步当心,步步入坑。html

一、本文要点

一、EventLoop是什么?
二、任务队列是什么?
三、同步任务和异步任务?
四、微任务和宏任务?
...
复制代码

二、EventLoop是什么?

咱们都知道Js是单线程语言,即同一时间只能作一件事情,可是为了协调各类事件、用户交互、脚本加载、UI渲染和网络处理等行为,避免主线不阻塞,出现了EventLoop => ==事件循环==也就是咱们常说的 异步 的方案。前端

过程:git

在执行主线程的任务时,若是有异步任务,会进入到Event Table并注册回调函数,当指定的事情完成后,
会将这个回调函数放到 callback queue 中

在主线程执行完毕以后,会去读取 callback queue中的回调函数,进入主线程执行

不断的重复这个过程,也就是常说的Event Loop(事件循环)了
复制代码

三、任务队列是什么?

事件循环是经过任务队列的机制来进行协调的。一个EventLoop中,能够有一个或者多个任务队列(task queue),一个任务队列即是一系列有序任务(task)的集合;每一个任务都有一个任务源(task source),源自同一个任务源的 task 必须放到同一个任务队列,从不一样源来的则被添加到不一样队列。github

在事件循环中,每进行一次循环操做称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤以下:

一、在这次 tick 中选择最早进入队列的任务(oldest task),若是有则执行(一次)
二、检查是否存在 Microtasks,若是存在则不停地执行,直至清空 Microtasks Queue
三、更新 render
四、主线程重复执行上述步骤
复制代码

四、同步任务和异步任务?

同步:必定要等任务执行完了,获得结果,才执行下一个任务。同步会阻塞代码运行,例如 alert
异步:异步任务会在异步任务有告终果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。。例如 setTimeout
复制代码

异步并非同步,异步是单线程,异步指的是让CPU暂时搁置当前请求的响应,处理下一个请求,当经过轮询或其余方式获得回调通知后,开始运行。面试

通俗的讲

同步就是我必须等到你的回复,才能作出下一步响应。即个人操做是顺序执行的,中间少了哪一步都不能够,或者说中间哪一步出错都不能够,若是我没有收到你的回复,我就一直处于等待、也就是阻塞的状态。ajax

异步则相反,对你响应的时间也不敏感,不管你返回仍是不返回,我都能继续运行;你响应并返回了,我就继续作以前的事情,你没有响应,我就作其余的事情。也就是说我不存在等待对方的概念,我就是非阻塞的。segmentfault

因此像setTimeOut定时任务、ajax请求都是须要必定的时间的,因此通常都是用异步方式,不会阻塞后边代码的执行,而是设置了定时时间以后、或发送了请求以后,就移动到单线程的任务队列的最尾端,等后边执行完以后再执行定时代码或者ajax请求的回调函数内代码。浏览器

注意:bash

异步并非Js同时执行两段操做,它只是设定了定时的时间,而后放到任务队列的最后面,而后去执行其余操做,当设定的时间到了以后在把事件拿回来继续执行。网络

五、微任务和宏任务?

异步任务又分为 宏任务(MacroTask)微任务(MicroTask),主要区别在于执行顺序的不一样。咱们都知道js应该是按照语句前后顺序执行,在出现异步时,则发起异步请求,再接着往下执行,待异步结果返回后再接着执行。

注意:

这两个任务分别维护一个队列,均采用先进先出的策略进行执行!同步执行的任务都在宏任务上执行。

宏任务队列macrotask一次只从队列中取一个任务执行,执行完后就去执行微任务队列中的任务;
微任务队列中全部的任务都会被依次取出来执行,知道microtask queue为空;
复制代码
5.1 宏任务(MacroTask)
  • script所有代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/O、UI Rendering。
5.2 微任务(MicroTask)
  • Promise、 MutationObserver、 process.nextTick(Node.js 环境)。
5.3 执行顺序

eventLoop.jpg

1.首先执行同步代码,这属于宏任务

2.当执行完全部同步代码后,执行栈为空,查询是否有异步代码须要执行

3.执行全部微任务

4.当执行完全部微任务后,若有必要会渲染页面

5.而后开始下一轮EventLoop,执行宏任务中的异步代码,也就是setTimeout中的回调函数
复制代码

六、结语

以前兜兜转转,老是忘记事件的执行顺序。长时间不接触,有些记忆愈加的淡忘。只能不断重拾记忆,加深。

参考资料

相关文章
相关标签/搜索