详解JavaScript的运行机制:Event Loop(事件轮询机制)

版权声明:转载需注明出处 https://blog.csdn.net/zf2014122891/article/details/85597721

前言

有人称Event Loop为事件循环机制,而我更愿意将其解释为事件轮询机制,在之后的内容中你会感受到这一点的区别在哪里。说是事件轮询机制,我们也可以说是任务轮询机制,因为英文是Event Loop,所以我们在此文中将其翻译为事件轮询。

阅读本文之前,首先对JavaScript的单线程和异步要有一定的了解,对此不了解的可以先阅读一下我的另一篇博文《JavaScript的单线程和异步》

ECMA只负责指定标准,Event Loop如何实现,它并不关心。
本文在概念的结构顺序上参考了阮一峰老师的博客《再谈javascript的运行机制: Event Loop》,理解也大多源于此文,加上个人看法,以更容易让读者理解的方式表述出来。

在讲JavaScript的事件轮询机制之前,让我们先来了解几个重要的概念:

任务队列

我们知道,由于JavaScript是单线程,这意味着所有任务都要排队等待执行,后面的任务要等待前面的任务执行结束才能开始执行,如果前一个任务耗时比较久的话,后一个任务就必须一直等待。

我们在《JavaScript的单线程和异步》一文中指出,CPU的运算能力往往是过剩的,我们等待的时间主要是IO操作的时间,这时候会发现,有时候javascript的主线程完全可以不管这些IO操作的任务,我们可以先将这些任务挂起,执行后面的任务,等到IO操作返回了结果,再将之前挂起的任务继续执行。

根据上述的情况,我们大致可以将这分为两种任务:同步任务(synchronous)异步任务(asynchronous)同步任务指主线程上排队等待被执行的任务,这些任务在一个执行栈中,顺序等待被执行,在主线程上的任务需要等待前一个任务执行结束才能被执行;异步任务是指那些被主线程挂起的任务,异步结果返回后一个事件被子线程放入“任务队列”中等待被读取进入主线程,而不是直接进入到主线程中等待被执行,这一点是要注意也是我们要着重强调的。而什么时候才会执行任务队列中的任务呢?我们先来看一张图:
任务队列流程图
捋一下整个流程:
步骤1: 首先解析JavaScript代码,这时代码未执行,将同步任务放到执行栈中等待被执行;
步骤2: 对执行栈进行判断,如果执行栈不为空则逐个执行排队的任务(任务执行过程中产生的异步任务抛给子线程进行处理,当任务结果返回时将一个事件放入任务队列中等待被读取);如果执行栈为空,则读取任务队列中可执行的事件,将其放到执行栈中等待被执行;
步骤3: 不断重复步骤2的操作。

注:任务队列也是一个先进先出的栈,先进入任务队列的任务会先被读取到执行栈中等待执行

注意:当执行栈空了,才会去读取任务队列,这个过程会不断重复。 这就是JavaScript的运行机制,没有我们想象的那么什么和复杂,对吧!

事件的概念

“任务队列"是一个事件的队列(也可以理解成消息的队列),异步操作完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列”,就是读取里面有哪些事件。
“任务队列"中的事件,还包括鼠标点击、键盘点击,定时操作等等。只要指定过回调函数,这些事件发生时就会进入"任务队列”,等待主线程读取。

回调函数

在讲事件轮询机制之前,我们还要了解一件事情,我们发起异步任务的目的是什么?是希望获得需要的结果,然后根据这个结果去做一些事情对吧,如果异步任务结果返回了,而我们什么都不做的话,就失去了发起异步任务的初衷!我们所谓的主线程挂起的任务,实际上是一段待执行代码,在异步结果或者说是状态返回时,我们执行这段代码,也就是执行异步任务;而这里的代码,我们称之为回调函数。

事件轮询机制Event Loop:

终于讲到在任务队列一章中我们放了一张图,主线程从"任务队列"中读取事件,这个过程是循环不断的,故此,我们将其称为Event Loop(直译为事件循环),照例,先摔一张图在这里:
事件轮询机制
上图中,主线程运行的时候,产生堆(heap)栈(stack),栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,error)。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。在这里我们能够更明确的看出任务队列是一个先进先出的数据结构。

这就像是每次执行栈为空时,便会询问任务队列是否有可执行任务,这也是我文章开头时为什么将Event Loop解释为事件轮询机制。

注:本文没有详细区分“任务队列“中的情况,之后会详解“任务队列”中的不同情况。

结语

此篇主要是讲解了JavaScript的运行机制,后面我们会从代码层面来深入分析JavaScript在代码层面的体现。

希望此文能够解决大家工作和学习中的一些疑问,避免不必要的时间浪费,有不严谨的地方,也请大家批评指正,共同进步!
转载请注明出处,谢谢!

交流方式:QQ1670765991

猜你喜欢

转载自blog.csdn.net/zf2014122891/article/details/85597721