JavaScript异步机制(二)之任务队列和事件循环

在这个系列的第一篇调用栈之后,今天想说说任务队列。 首先简单说下浏览器的进程线程。以Chrome浏览器为例,Chrome浏览器使用多个进程来隔离不同的网页。因此在Chrome中打开一个网页相当于起了一个进程。这一个进程中又包含多个线程,每个线程分别处理不同的任务,比如渲染页面,执行js等等。

一个浏览器进程通常由以下五个线程组成:

  1. GUI渲染线程。
  2. JavaScript引擎线程。
  3. 事件触发线程。
  4. 定时器线程。
  5. 异步HTTP请求线程。

GUI 渲染线程

GUI渲染线程负责渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被”冻结”了。

JavaScript引擎线程

Javascript引擎,也可以称为JS内核,主要负责处理Javascript脚本程序,例如V8引擎。Javascript引擎线程负责解析Javascript脚本,运行代码。

事件触发线程

当一个事件被触发时该线程会把事件添加到待处理事件队列的队尾,等待JS引擎的处理。这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

定时器线程

浏览器定时计数器并不是由JavaScript引擎计数的, 因为JavaScript引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。

异步HTTP请求线程

在XMLHttpRequest在连接后通过浏览器新开一个线程请求,在检测到状态变更时,会触发相应的事件,如果设置有回调函数,异步线程就产生状态变更事件,将事件处理程序放到 JavaScript引擎的处理队列中等待处理。

那么什么是任务队列呢?

任务队列

大家都知道JS是单线程的,假如在JS引擎执行代码的过程中触发了一些事件,那引擎会停下手中的事情来处理这些事件吗?当然不可能。那什么时候才能执行这些事件处理程序呢?在js引擎空闲的时候。实际上,无论是事件触发还是定时器还是HTTP请求,在各自的线程处理好对应的API之后,会把各自的事件处理程序放到一个叫做任务队列的数据结构中。在JS引擎空闲的时候会按顺序去执行每一个事件处理程序。按怎样的顺序?先进队列的先执行。这叫先进先出,和栈结构的后进先出正好相反。

事件循环

当JS引擎执行完代码之后,如果任务队列中有待处理的事件处理程序,那么JS引擎回去立即执行这些程序,那么假如现在任务队列是空的,但是过了一会有事件触发了,JS引擎是如何知道的呢?这就要讲到事件循环了。当JS引擎空闲的时候,他会不断的是轮询任务队列,如果有任务的话就去执行。

微任务

微任务包括promise的回调,mutationObserver的回调,以及nodejs的process.nextTick的回调。

宏任务

script全部代码。setTimeout,setInterval,setImmediate,I/O,UI Rendering

JS引擎初始执行代码如果遇到微任务,会将微任务放到微任务队列中,如果有宏任务,则将其放入宏任务队列。执行完代码后,会先去执行微任务队列中的事件,然后就是不断的事件循环。

我们可以把初始代码当成一个宏任务,在执行完这个宏任务之后,JS引擎会去处理本轮宏任务结束时的微任务队列,然后再去处理宏任务队列。所以执行微任务的时机就是在宏任务与宏任务之间。

更新视图

浏览器更新视图的时机是由其自己决定的,并不一定是宏任务与宏任务之间一定有视图的更新。可以确定的是,在JS引擎执行代码时,是不会更新视图的,因为GUI 渲染线程与JavaScript引擎线程互斥!浏览器会在适当的时机(宏任务与宏任务之间)更新视图,然后再继续执行代码。

GUI 渲染线程 与 JavaScript引擎线程互斥!

由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JavaScript线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。因此为了防止渲染出现不可预期的结果,浏览器设置GUI渲染线程与JavaScript引擎为互斥的关系,当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值