js 多个定时器_一图看懂浏览器环境下的JS事件循环

ee6163780ed554d1865b7cc67be2ae30.png

什么是事件循环机制

众所周知,js是单线程的。这意味着js一次只执行一个任务,且在当前任务执行完成之前,不会执行下一个任务。对于比较耗时的操作,比如从服务端获取数据,如果在请求过程中js一直等待服务器响应之后才执行后续任务,那么在此过程中就会造成阻塞。试想如果后续的任务并不依赖服务器返回的结果,有没有一种机制可以让js “跳过” 等待,继续执行后续任务呢?为了解决了这个问题,js把所有任务分为 同步任务异步任务。同步任务在主线程上运行,异步任务则都被放入 任务队列,不会阻塞主线程。主线程会不断从任务队列中读取任务,整个过程是循环不断的,所以这种机制被称为 事件循环。

宏任务 & 微任务

如上所述,所有的异步任务都被放入任务队列,然而任务队列并不对所有任务一视同仁,而是把任务分为两种:宏任务(macrotasks)微任务(microtasks)。宏任务被放入宏任务队列(macrotask queue),微任务被放入微任务队列(microtask queue)

常见的宏任务有解析HTML,执行主线程代码,定时器setTimeout, setInterval等;常见微任务有DOM变动,Promise。微任务是更新应用状态的微型任务,需要在浏览器进行其他操作(例如重渲染UI)之前执行。

事件循环的流程

事件循环应该至少包含一个宏任务队列和一个微任务队列。实际上,为了区别不同任务的优先级,事件循环可能会包含多个队列,用于存放不同类型的宏任务和微任务。事件循环建立在两个基本原则之上:

  1. 一次只执行一个任务
  2. 一个任务在执行完成前不能被其他任务打断

请先看下图(图片来源于 Secrets of the Javascript):

c088b81914b5fe75bdb06c25f893ca76.png
事件循环可以访问宏任务队列和微任务队列,两种任务都是一次只执行一个。单次循环最多处理一个宏任务,但会处理所有的微任务。

js执行完主线程之后,会检查宏任务队列中是否有等待执行的宏任务。若有,会从宏任务里提取一个最先入队的任务,此任务执行完成之后,进行下一步;若没有,则直接进行下一步。

接下来,事件循环会处理微任务队列。若微任务队列里有等待执行的微任务,事件循环会提取任务并执行完成,完成之后,会继续检查微任务队列中是否有等待执行的微任务。此过程会一直循环,直至微任务队列被清空。

至此,我们已看出事件循环处理宏任务队列和微任务队列的不同之处:在单次循环中,最多只会处理一个宏任务,但是会处理所有的微任务

当微任务队列被清空之后,事件循环会检查是否有必要更新渲染UI,若需要,则会重渲染UI。至此,此次循环完成,然后事件循环会继续检查宏任务队列,开启下一次循环。

图中有几个细节需要注意:

  1. 任务队列处于事件循环之外。 这表示添加任务到对应队列的动作发生在事件循环之外。试想一下,如果不是这样的话,所有发生在js执行过程中的事件都会被忽律。为了避免丢失事件,检测和添加任务的动作都被独立于事件循环之外。
  2. 两种任务都是一次只执行一个任务
  3. 所有的微任务都需要在下次渲染之前完成,因为它们的目标就是在下次渲染之前更新应用状态。
  4. 为了达到60帧率(60fps),浏览器每秒会有60次尝试渲染面。这意味着若想让页面更加丝滑,在单次事件循环里我们没有太多时间用于执行任务。在理想状态下,一个任务和它生成的所有微任务,都应在16ms内完成

请思考以下几个问题:
1. setTimeout(fn, 10), fn一定会在10毫秒时被调用吗?
1. setInterval(fn, 10), fn一定会每隔10秒执行一次吗?若执行100毫秒,fn一定会调用10次吗?

我会在后续的文章中对以上问题进行解答,并详情阐述原因。如果你觉得这片文章还不错的话,敬请期待。若对文中内容有异议,欢迎指正讨论。


参考文献

  1. Secrets of the Javascript
  2. 阮一峰 - JavaScript 运行机制详解:再谈Event Loop
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值