javaScript异步编程--浏览器事件循环机制

本文详细阐述了浏览器的Event Loop机制,包括进程与线程概念,单进程与多进程架构选择,以及关键线程如GUI渲染线程、JS引擎线程和事件队列的工作原理。重点讲解了同步任务、异步任务、宏任务与微任务的区别,以及它们如何通过事件循环驱动JavaScript执行。
摘要由CSDN通过智能技术生成

实现

JavaScript 事件循环机制以运行时环境划分,可分为浏览器、Node.js及Deno事件循环机制,三者的实现技术不一样:

  • 浏览器 Event Loop 是 HTML 中定义的规范;
  • Node.js Event Loop 是由 libuv 库实现;
  • Deno Event Loop 是 由 Rust 语言的 Tokio 库实现。

这里只讲浏览器部分。

进程、线程

进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的。
线程是进程的执行流,是CPU调度和分派的基本单位,同个进程之中的多个线程之间是共享该进程的资源的。

浏览器进程

在这里插入图片描述
浏览器模式一般有两种,单进程架构和多进程多线程架构。现代浏览器基本上都是后者了。

因为现在网页复杂性非常高,如果整个浏览器是单进程的,有可能某个page界面的抛错就会导致整个浏览器的崩溃。同时多个界面互相可以访问相同的内存和相同的执行环境,安全性也是一个大的问题,所以浏览器需要采用多进程模式。
以chrome为例,浏览器的进程大概分为以下这几种:

  • 浏览器主进程(Browser进程):控制chrome的地址栏,书签栏,返回和前进按钮,同时还有浏览器的不可见部分,例如网络请求和文件访问。
  • 第三方插件进程:每种插件一个进程,插件运行时才会创建。
  • 浏览器渲染进程(也被称为浏览器内核,内部是多线程的):负责界面渲染,脚本执行,事件处理等。
  • GPU进程:最多一个,用于3D绘制。
  • 工具进程:比如我们调试的控制台。

浏览器内核

浏览器是多进程的,浏览器每一个 tab 标签一般代表一个独立的进程(多个空白 tab 标签会合并成一个进程),浏览器内核(浏览器渲染进程)属于浏览器多进程中的一种。

浏览器内核有多种线程在工作。
在这里插入图片描述

GUI 渲染线程

负责渲染页面,解析 HTML,CSS 构成 DOM 树等,当页面重绘或者由于某种操作引起回流都会调起该线程。
和 JS 引擎线程是互斥的,当 JS 引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI 更新被放入在 JS 任务队列中,等待 JS 引擎线程空闲的时候继续执行。

JS 引擎线程

单线程工作,负责解析运行 JavaScript 脚本。它一般就是我们常说的主线程。
和 GUI 渲染线程互斥,JS 运行耗时过长就会导致页面阻塞。

事件触发线程

当事件符合触发条件被触发时,该线程会把对应的事件回调函数添加到任务队列的队尾,等待 JS 引擎处理。

定时器触发线程

浏览器定时计数器并不是由 JS 引擎计数的,阻塞会导致计时不准确。
开启定时器触发线程来计时并触发计时,计时完成后会被添加到任务队列中,等待 JS 引擎处理。

http 请求线程

http 请求的时候会开启一条请求线程。
请求完成有结果了之后,将请求的回调函数添加到任务队列中,等待 JS 引擎处理。

从上面可以看出,JS 引擎线程外的其它线程的后续工作都会添加到任务队列中。
而JS引擎线程是单线程,每次只能执行一项任务,其它任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后才会往下执行下一个任务。

同步任务、异步任务

JavaScript 单线程中的任务分为同步任务和异步任务。
同步任务会在调用栈中按照顺序排队等待主线程执行;
异步任务则会在异步有了结果后,将注册的回调函数添加到任务队列中,等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中等待主线程执行。

Event Loop

调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。

每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环(event loop)。
在这里插入图片描述

宏任务(macro-task)、微任务(micro-task)

除了广义的同步任务和异步任务,JavaScript 单线程中的任务还可以细分为宏任务和微任务。
macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O等
micro-task包括:process.nextTick, Promise, Object.observe(已废弃), MutationObserver
在这里插入图片描述
宏任务本质,是参与了事件循环的任务,就是上面图上的GUI渲染线程、事件触发线程、定时器触发线程、http请求线程传递过来的消息。

微任务本质,是直接在 Javascript 引擎中执行的,没有参与事件循环的任务。它是V8的一个实现,本质上它和当前的V8调用栈是同步执行的,只是放到了最后面。类似于hooks,像是一个后门,专门在宏任务执行完成后,执行所有微任务,执行完成后,才会进行下一轮宏任务。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值