突破浏览器单线程限制(4),Fetch API、音频处理、WebGL与WebGPU的革新之旅

突破浏览器单线程限制(4),Fetch

在Web开发中,浏览器的单线程模型曾经限制了Web应用的性能,但随着技术的发展,出现了一些技术手段可以突破这一限制,实现多任务并行处理。以下是一些突破浏览器单线程限制的技术,包括Fetch API、Web Audio API、WebGL和WebGPU。
### Fetch API
Fetch API 是一个现代的、基于Promise的HTTP客户端,用于在网络上发起请求。它不是Web API的一部分,但它允许开发者以非阻塞的方式发起网络请求。
```javascript fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ```
Fetch API 的优势在于:
- "非阻塞":它不会阻塞主线程,允许浏览器继续处理其他任务。 - "Promise":它使用Promise,使得异步代码更易于管理。 - "CORS":它支持跨源资源共享(CORS),使得跨域请求更加方便。
### Web Audio API
Web Audio API 是一个用于处理音频的JavaScript API,它允许开发者创建复杂的音频处理流程,而不需要使用传统的HTML5 `

相关内容:

前情提要

前面介绍了三种 Web Worker,它们是主要的突破浏览器单线程手段。

  1. 突破浏览器单线程(1):Dedicated Worker
  2. 突破浏览器单线程(2):Shared Worker
  3. 突破浏览器单线程(3):Service Worker
此外,还有一些自由度不高的特殊手段,以及一些伪突破手段。

伪突破1:非阻塞回调

利用事件循环(Event Loop),可以将任务拆分为非阻塞操作。 比如:

  • setTimeout/setInterval:延迟执行。
  • Promise/async/await:处理异步任务链。
  • requestIdleCallback:在浏览器空闲时执行低优先级任务。
前两个比较常见,这里给出一个 requestIdleCallback 示例:

// 分片处理大数据
function processChunk(data, chunkSize) {
  let index = 0;
  function next() {
    const chunk = data.slice(index, index + chunkSize);
    if (index < chunk.length) {
      // 处理当前分片
      requestIdleCallback(() => next());
      index += chunkSize;
    }
  }
  next();
}
通过异步回调,以上代码可以在空闲时,异步递归执行,处理一个非常大的 data 。

但需要注意的是,这些手段,尽管看上去像是并行(Parallel),但归根结底都是单线程的并发(Concurrent)。如果真的执行计算密集型任务,会阻塞 UI 线程,造成界面卡顿,甚至可能造成整个浏览器所有页面的卡顿。

可以类比为Python里的协程,无论底下怎么实现,由于有 GIL 在,相当于还是一条线程去轮流执行。如果某个协程同步卡死,所有其它协程都不会运行。

这个手段,只适合处理 IO 类操作,并做一些 IO 前后的过程处理。最常见的 IO 例子是,网络请求。

伪突破2:WASM

WebAssembly(简称WASM)是一种低级的二进制指令格式,专为在Web浏览器中高效执行而设计。它由主流浏览器厂商共同开发,旨在弥补JavaScript在性能密集型任务上的不足。WASM代码通常由C/C++、Rust等语言编译生成,具有接近原生的运行速度,同时保持跨平台兼容性。其核心优势在于通过预编译的二进制格式实现快速加载和执行,尤其适用于游戏、音视频处理、加密计算等场景。WASM运行在浏览器的沙盒环境中,安全性通过严格的内存隔离和类型检查机制保障。

WASM

尽管WASM性能出色,但它目前仍受限于单线程模型。这意味着WASM模块默认只能在一个主线程中运行,无法直接利用多核CPU的并行计算能力。这种限制源于Web平台的传统设计——浏览器的主线程负责处理DOM操作和事件循环,而WASM作为其扩展同样遵循这一规则。虽然通过Web Worker可以实现多线程,但线程间通信必须通过消息传递(postMessage),且无法共享内存(除非使用SharedArrayBuffer),这增加了复杂性和性能开销。对于需要大规模并行计算的应用(如3D渲染或科学模拟),单线程限制可能成为瓶颈。

所以,还是要和前面介绍的三种 Worker 结合使用。让 WASM 的代码运行在某个 Worker 中,才能实现在 UI 以外的线程运行,避免阻塞界面操作。

特殊手段1:Fetch API

Fetch API 是浏览器提供的用于发起网络请求的现代接口,相较于传统的 XMLHttpRequest,它具有更简洁的语法和基于 Promise 的异步处理机制。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('请求失败:', error));
这里展示了一个极简示例,它有明显的异步特征。其异步处理回调函数,比如两个 then 和一个 catch,都是在 UI 线程运行的。

然而,关键在第一行。真正在执行网络请求时,是在浏览器特别的独立线程运行。

为避免资源滥用和性能问题,对网络请求施加了以下限制:

浏览器/并发数

HTTP/1.1

单域名

HTTP/1.1

全局

HTTP/2

多路复用支持

备注

Chrome

6

10

✅ 支持

(无严格并发数限制)

HTTP/2并发无限制,但TCP连接只有1个

Firefox

6

13

✅ 支持

(默认启用多路复用)

可配置
network.http.max-connections

Edge

6

10

✅ 支持

(类似 Chrome)

基于 Chromium 内核,行为与 Chrome 一致

Safari

6

10

✅ 支持

(6 个流/域名)

移动端(iOS)全局限制可能更低

Opera

6

10

✅ 支持

基于 Chromium,限制与 Chrome 相同

IE 6

2

4

❌ 不支持 HTTP/2

已淘汰,仅作参考

IE 11

6

10

❌ 不支持 HTTP/2

已淘汰,仅作参考

HTTP/2 多路复用,是指在1个TCP连接下,可以跑多个。它不像 HTTP/1.1,需要独立线程来支持并发。但是底下仍然有连接数和线程池的限制。另外,服务端也可能对单个客户端的并发数做限制。

总之,走 Fetch API 的网络请求,实际是运行在独立线程中的。但是这些线程都属于浏览器,前端开发者无法直接利用,运行自己的代码。

特殊手段2:Web Audio API

Web Audio

Web Audio API是现代浏览器提供的一套高性能音频处理接口,专为网页端的专业级音频应用而设计。它采用模块化架构,将各种音频功能抽象为可连接的节点,如振荡器、滤波器、增益控制器等,开发者可以通过构建音频节点图实现复杂的音频处理流程。这套API不仅支持基础的音频播放和合成,还能实现3D空间音效、精确时间调度和实时音频分析等高级功能,广泛应用于在线音乐制作、游戏音效和交互式音频体验等场景。

Web Audio API的核心特性是其独特的线程模型设计。与常规Web API不同,它运行在浏览器专门创建的音频渲染线程中,与主JavaScript线程完全分离。这种架构确保了音频处理的实时性,即使主线程因复杂计算或DOM操作出现卡顿,音频播放仍能保持流畅。主线程与音频线程之间通过消息队列通信,所有音频参数变化会被批量处理,从而减少线程间频繁交互带来的性能开销。这种设计使Web Audio API能够满足专业音频应用对低延迟和高稳定性的严苛要求。

传统Web Audio的ScriptProcessorNode存在明显性能缺陷,因为它需要在主线程处理音频数据。为解决这一问题,现代浏览器引入了AudioWorklet机制。AudioWorklet允许开发者将自定义音频处理代码直接运行在音频线程中,彻底避免了主线程和音频线程间的数据拷贝。开发者可以创建继承自AudioWorkletProcessor的类,实现特定的process方法来处理音频流,并通过registerProcessor方法注册这些自定义处理器。这种机制既保证了音频处理的实时性,又提供了足够的灵活性。

在实际应用中,AudioWorklet 的使用分为三个关键步骤:首先通过audioWorklet.addModule加载处理器脚本,然后创建对应的AudioWorkletNode实例,最后将其接入音频节点图。处理器脚本必须单独存放于独立文件中,其中定义的process方法会实时接收输入音频数据,处理后输出结果。这种方法特别适合实现自定义音效、合成器或实时音频分析等需要高性能处理的功能,如噪声抑制、均衡器或复杂的音频合成算法。

Web Audio API及其AudioWorklet机制共同构成了Web平台强大的音频处理能力。这种设计既考虑了Web安全沙箱的限制,又通过专用线程和高效通信机制实现了接近原生应用的音频性能。随着WebAssembly等技术的引入,未来Web音频处理的能力还将进一步增强,使浏览器成为越来越强大的音频应用平台。对于需要精细控制音频的Web应用开发者来说,深入理解这套API的线程模型和工作原理至关重要。

在音频线程,处理音频即可,最好不要搞其它事情,以免音频卡顿。

特殊手段3:WebGL

WebGL(Web Graphics Library)是一种基于JavaScript的API,允许开发者在浏览器中直接渲染高性能的2D和3D图形,而无需依赖插件。它基于OpenGL ES标准,通过HTML5的Canvas元素实现硬件加速,使得复杂的图形计算能够利用GPU的能力。WebGL的核心优势在于其跨平台性和易用性,开发者只需编写一次代码即可在多种设备和操作系统上运行。它广泛应用于游戏开发、数据可视化、虚拟现实等领域,成为现代Web图形技术的基石。

WebGL

WebGL的线程模型是其高效运行的关键之一。与传统的Web技术不同,WebGL主要运行在浏览器的渲染线程中,但它的实际图形计算任务会被转移到GPU线程执行。这种设计避免了JavaScript主线程的阻塞,使得图形渲染与页面逻辑可以并行处理。当开发者调用WebGL API时,指令会被封装成命令队列,由浏览器调度到GPU线程执行。这种异步机制显著提升了性能,但也要求开发者注意指令的顺序和同步问题,例如纹理加载或缓冲区操作的延迟。

在WebGL的线程模型中,主线程(JavaScript线程)负责生成渲染命令,而GPU线程负责执行这些命令。两者之间的通信通过命令缓冲区(Command Buffer)实现,主线程将WebGL调用序列化为命令并提交到缓冲区,GPU线程从中读取并执行。由于跨线程通信存在开销,WebGL优化了高频调用(如批量绘制操作)以减少线程切换。此外,WebGL 2.0进一步引入了更高效的机制,例如Transform Feedback,允许GPU直接回传数据到顶点着色器,减少主线程干预。

WebGL底层,可能是OpenGL,或者DirectX

WebGL的多线程特性也带来了一些挑战。例如,资源加载(如纹理或着色器)需要跨线程同步,若处理不当可能导致渲染延迟或闪烁。为解决这一问题,WebGL提供了事件通知和状态查询机制,开发者可以通过回调或轮询确保资源就绪。另一个挑战是线程安全:WebGL上下文绑定到单个线程,若在多线程环境中错误共享上下文会导致错误。因此,现代浏览器通常将WebGL上下文限制在主线程或专用Worker中,通过OffscreenCanvas支持后台线程渲染。

特殊手段4:WebGPU

WebGPU 是新一代的 Web 图形 API,旨在为现代 GPU 提供更高效、更灵活的低级访问能力,同时解决 WebGL 的诸多限制。它基于 Vulkan、Metal 和 Direct3D 12 等原生 GPU API 设计,提供了更接近硬件的控制能力,适用于高性能图形渲染和通用计算(GPGPU)。WebGPU 的核心优势在于其更低的 CPU 开销、更好的多线程支持,以及更合理的资源管理机制。它的出现使得 Web 应用能够更高效地利用 GPU,适用于游戏、科学计算、机器学习等高性能场景。

WebGPU

WebGPU 的线程模型相比 WebGL 有了显著改进。WebGL 主要依赖单线程渲染,而 WebGPU 从设计之初就支持多线程协作。在 WebGPU 中,核心对象(如设备 GPUDevice、命令队列 GPUQueue)可以被多个 Worker 线程共享,允许并行录制命令缓冲区(Command Buffer)。这意味着计算任务、渲染任务可以分散到不同线程执行,再统一提交到 GPU,大幅提升 CPU 并行度。此外,WebGPU 引入了更精细的同步机制(如栅栏 GPUFence 和信号量),确保多线程操作的安全性,避免资源竞争。

与 WebGL 相比,WebGPU 的线程模型更加灵活且高效。WebGL 的渲染指令必须在主线程或 OffscreenCanvas 的 Worker 线程中执行,而 WebGPU 允许在任意 Worker 线程中创建和提交 GPU 命令。WebGL 的图形管线是固定且全局的,而 WebGPU 采用可编程的管线对象(如 GPURenderPipeline),可以在不同线程中并行构建。此外,WebGPU 的资源绑定模型(如 GPUBindGroup)更加显式,减少了隐式状态切换,使得多线程环境下的资源管理更可控。

WebGPU 的另一个关键区别是它对计算着色器(Compute Shader)的原生支持,而 WebGL 只能通过图形管线模拟计算任务。这使得 WebGPU 更适合通用 GPU 计算(如物理模拟、AI 推理)。计算管线可以独立于渲染管线运行,并允许更细粒度的线程组调度(如 GPUComputePass 中的工作组分发)。相比之下,WebGL 的计算能力受限,且难以高效利用多线程优化性能。

苹果在2017年的WebGPU提案

未来,WebGPU 有望逐步取代 WebGL,成为 Web 图形和计算的新标准。它的线程模型设计更符合现代 GPU 架构,能够更好地利用多核 CPU 和 GPU 并行计算能力。开发者若需要高性能图形或通用计算,WebGPU 提供了更优的选择,而 WebGL 仍适用于简单的、兼容性要求高的场景。两者的主要差异体现在线程控制、资源管理、计算能力等方面,WebGPU 在这些方面均提供了更先进的解决方案。

总结

从突破单线程的角度,本文考察了当代浏览器的所有基础设施。

常用的、自定义程度高的,要数三种 Web Worker。Fetch API 背后的网络线程,是浏览器的自留地,可以间接使用,直接碰不到。Audio API 背后有一个音频线程,可以对音频做一些前后处理,但不推荐搞别的事情。

WebGL 与 WebGPU,是很好的并行计算手段。它们不仅支持多线程,而且还能间接使用 GPU 进行计算,适合承担大量计算任务。二者都很复杂,本文并未深入介绍。

WASM 是一个很好的配套手段,但不能单独用,否则默认还是挤在 UI 线程里。

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章