事件循环 js事件循环、node事件循环、浏览器事件循环

1. 事件循环

JS引擎是单线程的,一个时间点下JS引擎只能做一件事情。

在浏览器环境中,有JS 引擎线程和渲染线程,且两个线程互斥。
Node环境中,只有JS 线程。

JS的任务分为异步和同步两种

  • 异步:一个任务不是连续完成的,先执行第一段,做好准备之后,再回过头执行第二段(回调)。
  • 同步:连贯完成的。

eg:读取文件、网络请求等任务属于异步任务:花费时间长,但中间的操作不需要JS引擎自己完成,它只需要等别人准备好,把数据给它,它执行回调部分。

如果没有特殊处理,JS 引擎在执行异步任务时,应该是存在等待的,不去做任何其他事情。用一个图来展示这个过程,可以看出,在执行异步任务时有大量的空闲时间被浪费。
在这里插入图片描述

为了不使JS引擎处于忙等的状态,采取了异步任务回调通知模式:
在这里插入图片描述

在等待异步任务准备的同时,JS 引擎去执行其他同步任务,等到异步任务准备好了,再去执行回调。这种模式的优势显而易见,完成相同的任务,花费的时间大大减少,这种方式也被叫做非阻塞式。

实现这个“通知”的,正是事件循环,把异步任务的回调部分交给事件循环,等时机合适交还给 JS 线程执行。事件循环并不是 JavaScript 首创的,它是计算机的一种运行机制。


2. 任务队列

事件循环是通过任务队列的机制进行协调的。

一个事件循环中,可以有一个或者多个任务队列(task source),源自同一个任务源的task必须放到同一个任务队列,从不同源来的则被添加到不同的队列。

事件循环是由一个队列或者多个队列组成的,异步任务的回调遵循先进先出,在 JS 引擎空闲时会一轮一轮地被取出,所以被叫做循环。
在这里插入图片描述

JS引擎常驻于内存中,等待宿主将JS代码或函数传递给它。
也就是等待宿主环境分配宏观任务,反复等待 - 执行即为事件循环。

Event Loop(事件循环)中,每一次循环称为tick,每一次tick的任务如下

  • 在此次 tick 中选择最先进入队列的任务(oldest task),如果有则执行(一次)
  • 检查是否存在 Microtasks,如果存在则不停地执行,直至清空 Microtasks Queue
  • 更新 render
  • 主线程重复执行上述步骤。

对于每一次循环tick:

  • JS分为同步任务和异步任务。
  • 同步任务都在主线程上执行,形成一个执行栈。
  • 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有运行结果,就在任务队列中放置一个事件。
  • 一旦执行栈中所有同步任务执行完成(JS引擎空闲),系统就会读取任务队列,将可运行的任务队列加入执行栈中,开始执行。

根据队列中任务的不同,分为宏任务微任务


3. 宏任务、微任务

事件循环由宏任务和执行宏任务期间产生的所有微任务组成。
完成当下的宏任务后,会立即执行所有在此期间入队的微任务。
在这里插入图片描述

这种设计是为了给紧急任务一个插队的机会,否则新入队的任务永远被放在队尾。
区分了微任务和宏任务后,本轮循环中的微任务实际上就是在插队,这样微任务中所做的状态修改,在下一轮事件循环中也能得到同步。

举个小例子:

console.log('script start');
 
setTimeout(function() {
   
  console.log('setTimeout');
}, 0);
 
Promise.resolve().then(function() {
   
  console.log('promise1')
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南栀~zmt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值