JavaScript知识点之Event Loop

前言

之前在阅读Js书籍时,就看见过事件循环的概念。最近又阅读了相关的文章以及setTimeout(fn, 0)背后所涉及的知识点,所以结合以前阅读的文章以及最近学习到的相关知识点,总结下Event Loop相关知识。

JavaScript线程

浏览器中至少存在三个线程:

  1. JavaScript引擎:基于事件驱动的单线程
  2. GUI渲染:与Js引擎互斥,当页面需要重绘或回流时执行
  3. 事件触发:将事件处理程序添加到任务队列中,等待Js引擎解释执行

我们常说的浏览器内核实际上指的是渲染引擎,负责UI的渲染的,当你通过DOM改变页面节点的样式时,页面就会重绘,该引擎就会工作。

我们知道JavaScript是单线程的,这里所说的JavaScript是单线程的就是指Js引擎线程,它是所有Js代码执行的地方,而Js引擎内部就是基于事件驱动的。

Js引擎内部中事件驱动是怎样的实现原理呢?简单地说,

实际上内部维持着一个队列。这个队列被称为任务队列,该队列中存储着所有被触发的异步处理程序,引擎通过循环形式将异步程序程序入栈处理

while(true) {
	// tick
}

每一轮循环称为tick,当事件被触发,事件处理程序就会被加到队列的队尾,因为是单线程,所以需要等待队列中其他程序执行完毕才可以执行该事件程序。

Js事件循环(Event Loop)实际上就是如此实现的:

当事件被触发,处理程序加入到任务队列中等待Js引擎的执行,所有的任务都是排队等待被执行。

我们知道Js是解释型语言(实际上js存在编译),代码是从上到下依次执行的,对于未来执行的代码称为异步代码,相对的不异步执行的就是同步代码。

简单的说,Js引擎在执行同步异步代码的过程大概如此:

  1. 所有的同步任务在主线程上执行,形成执行栈。
  2. 主线程之外,存在任务队列,只要异步任务有了结果,就会在任务队列中放置相关的任务,等待同步任务被执行完后,由引擎循环入栈异步程序开始执行。

实际上, Js引擎内部优先执行同步代码,同步代码不执行完是不会执行异步代码的,即不会将任务队列中的异步代码入栈执行。

下面看一个实例,就明白了上面的意思:
代码
结果:
结果

我们可以看出,输出b的定时器是在for循环之后才输出的,为什么会如此?

因为Js引擎中同步代码没有执行完,引擎不会循环将任务队列中的异步事件处理程序入栈处理

那么此处setTimeout(fn, 0)表示何意呢?难道不是立即执行吗?实际上说立即执行不是很准确,准确的描述是:

当同步代码执行完毕后,立即执行该定时器中异步代码

我们已经知道Js单线程以及内部Event Loop的大概执行思路,那就明白了异步事件执行以及定时器都是存在精度问题,它们精度都要取决于异步代码被入栈执行的时间,而入栈时间取决于同步代码执行的快慢。

总结
  • Js引擎内部Event Loop机制用于处理异步处理程序
  • 任务队列存储所有被触发的异步程序
  • Js引擎处理完所有的同步代码之后,才会通过Event Loop机制获取任务队列中队列头部的程序,并入栈进行处理
  • Event Loop机制内部实现简单点来说就是一个无限循环
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值