JavaScript事件循环

单线程和异步

为什么JavaScript引擎是单线程的?为什么JavaScript要引入异步编程?这些都是老生常谈,不做赘述。值得说明的是,js的事件循环正是用来实现异步特性的。

事件循环概述

js的执行机制就是事件循环。js在执行时,有以下几个主要部分参与了事件循环。

  1. 执行栈,用来创建执行环境,执行js代码
  2. 异步处理模块,用来处理异步事件
  3. 任务队列,包括宏任务队列和微任务队列,用来控制消息的生产消费

事件循环的过程为:当执行栈空的时候,就会从任务队列中,取任务来执行。共分3步:

  1. 取一个宏任务来执行。执行完毕后,下一步。
  2. 取一个微任务来执行,执行完毕后,再取一个微任务来执行。直到微任务队列为空,执行下一步。
  3. 更新UI渲染。

其中,UI渲染会根据浏览器的逻辑,决定要不要马上执行更新,不一定在本次循环中立即执行。可以看到,事件循环中包含UI渲染,这就是为什么我们说js的执行会阻塞UI渲染。

任务队列

任务队列里保存的,是事件的回调函数,异步处理模块就负责将异步事件回调插入到任务队列中。比如,定时器模块执行setTimeout方法后,会在计时结束后,将回调函数加入到相应的宏任务队列中去。

宏任务队列和微任务队列

  1. 宏任务队列可以有多个,微任务队列只有一个
  2. 宏任务有 script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering。微任务有 process.nextTick, Promise, Object.observer, MutationObserver。
  3. 宏任务队列有优先级之分。每次js引擎从宏任务队列中取宏任务时,会按照优先级选择宏任务队列,若高优先级的宏任务队列中没有任务时,才会到低级的宏任务队列中去取任务。
  4. 为什么会有宏任务和微任务之分呢?个人理解,宏任务才是真正意义上的任务,而微任务相当于宏任务的附属的一系列操作和相应。所以,js引擎每次取出一个宏任务执行,并且执行相关的微任务,这样保证一个完整的任务被执行完。这也是微任务队列只有一个的原因,微任务队列就是用来辅助宏任务队列的任务的完整执行的。而宏任务队列才是真正意义的任务,任务有优先级之分就很好理解了,因此才有多个宏任务队列,就是为了区分优先级。

执行过程

首先,js引擎从宏任务队列中取任务,因为script(全局)宏任务队列的优先级最高,因此先将这个任务取出(这个任务是当前所有可执行脚本),并利用执行栈执行这些脚本。在执行过程中,会产生一些异步操作,将之交由异步处理模块处理。异步处理模块会产生一系列异步回调,加入到任务队列中。当前执行栈执行完(栈为空)时,再执行微任务队列中的所有任务。执行完后,再从根据优先级从宏任务队列中取出一个任务执行,然后再从微任务队列中取任务执行直到微任务队列为空。 就这样循环往复,生生不息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值