浅析 JS 中的 EventLoop 事件循环(新手向)

Posted SegmentFault

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析 JS 中的 EventLoop 事件循环(新手向)相关的知识,希望对你有一定的参考价值。

内容来源:公众号 - 码力全开
作者:savokiss
整理编辑:SegmentFault




Event Loop 这个概念相信大家或多或少都了解过,但是有一次被一个小伙伴问到它具体的原理的时候,感觉自己只知道个大概印象,于是计划着写一篇文章,用输出倒逼输入,让自己重新学习这个概念,同时也能帮助更多的人理解它~



概念



javascript 是一门  单线程  语言,即同一时间只能执行一个任务,即代码执行是同步并且阻塞的。

eg. 这就像只有一个窗口的银行,客户需要一个一个排队办理业务。

只能同步执行肯定是有问题的,所以 JS 有了一个用来实现异步的函数: setTimeout

下面要讲的 Event Loop 就是为了确保 异步代码 可以在 同步代码 执行后继续执行的。

由于涉及到的相关概念较多,我们先从最简单的来。



队列(Queue)



队列 是一种 FIFO (First In, First Out) 的数据结构,它的特点就是 先进先出。

eg. 生活中最常见的例子就是排队啦,排在队伍最前面的人最先被提供服务。



栈(Stack)



栈,是一种 LIFO (Last In, First Out) 的数据结构,特点即 后进先出。

eg. 大家都吃过桶装薯片吧~薯片在包装的时候只能从顶部放入,而吃的时候也只能从顶部拿出,这就叫后进先出哈



调用栈(Call Stack)



栈我们已经知道了,那么什么是 调用栈 呢 ?

它本质上当然还是个栈啦,关键在于它里面装的东西,是一个个待执行的函数。

Event Loop 会一直检查 Call Stack 中是否有函数需要执行,如果有,就从栈顶依次执行。同时,如果执行的过程中发现其他函数,继续入栈然后执行。

先拿两个函数来说:

  • 栈空
  • 现在执行到一个 函数A,函数A 入栈
  • 函数A 又调用了 函数B,函数B 入栈
  • 函数B 执行完后 出栈
  • 然后继续执行 函数A,执行完后A也 出栈
  • 栈空

更复杂一点的话,来看一段代码:

浅析 JS 中的 EventLoop 事件循环(新手向)

这段代码在 调用栈中的运行顺序如下图:

浅析 JS 中的 EventLoop 事件循环(新手向)
这个调用栈其实大家经常会见到,就是在控制台报错的时候,错误信息显示的就是当前时刻调用栈的状态。

But, 上面我们讨论的其实都是同步代码,代码在运行的时候只用 调用栈 解释就可以了。

那么,假如我们发起了一个网络请求(request),或者设置了一个定时器延时(setTimeout),一段时间后的代码(回调函数)肯定不是直接被加到调用栈吧?

这时就要引出  事件表格(Event Table)   和  事件队列 (Event Queue) 



Event Table



Event Table 可以理解成一张  事件->回调函数  对应表

它就是用来存储 JavaScript 中的异步事件 (request, setTimeout, IO等) 及其对应的回调函数的列表


Event Queue



Event Queue 简单理解就是 回调函数 队列,所以它也叫 Callback Queue

当 Event Table 中的事件被触发,事件对应的 回调函数 就会被 push 进这个 Event Queue,然后等待被执行


Event Loop



先来看一个流程图:

浅析 JS 中的 EventLoop 事件循环(新手向)
  • 开始,任务先进入 Call Stack
  • 同步任务直接在栈中等待被执行,异步任务从 Call Stack 移入到 Event Table 注册
  • 当对应的事件触发 (或延迟到指定时间) ,Event Table 会将事件回调函数移入 Event Queue 等待
  • 当 Call Stack 中没有任务,就从 Event Queue 中拿出一个任务放入 Call Stack


而 Event Loop 指的就是这一整个圈圈:

它不停检查 Call Stack 中是否有任务(也叫栈帧)需要执行,如果没有,就检查 Event Queue,从中弹出一个任务,放入 Call Stack 中,如此往复循环。


好啦,不知道有没有看明白呢?放一张更经典的图:


其中与  Event Queue 对应的还有一个叫 Job Queue ,它主要是用来执行 Promise 的,还 涉及到了 宏任务 (macro task) 微任务 (micro task ) 了。

参考文章:


MDN EventLoop
javascript-event-loop
understanding-js-the-event-loop
这一次,彻底弄懂JavaScript执行机制
understanding-event-loop-call-stack-event-job-queue-in-javascript

- END -


以上是关于浅析 JS 中的 EventLoop 事件循环(新手向)的主要内容,如果未能解决你的问题,请参考以下文章

浅析JS堆栈执行栈和EventLoop

浅析Vue.nextTick()原理

详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务

搞懂js中 eventloop事件循环和Promise面试题

前端中的事件循环eventloop机制

吊打面试官之一文吃透JS事件循环EventLoop