Web Worker核心背景
- JavaScript 在浏览器中默认运行在单一的“主线程”上。
- 该线程负责执行 JavaScript 代码、处理用户交互(点击、滚动、输入)、更新 UI(DOM 操作、样式计算、布局、绘制)以及处理网络事件等所有任务。
- 如果一个任务(例如复杂的计算、大数据处理、长时间运行的循环)占据了主线程,整个页面就会失去响应:UI 冻结、用户交互无反应、动画卡顿。用户体验极其糟糕。
- 随着 Web 应用变得越来越复杂(图形处理、科学计算、大型数据集操作、实时通信、游戏等),需要处理的计算密集型任务也越来越多。
- 将这些任务放在主线程执行会严重拖慢整个应用的响应速度和渲染性能,即使这些任务本身是异步的(如
setTimeout、Promise),它们最终仍需在主线程排队执行,无法充分利用现代多核 CPU 的并行计算能力。
「Web Worker 的出现就是为了解决这些问题:」
- 「创建独立线程:」 Web Worker 允许开发者创建在「独立于主线程的后台线程」中运行的 JavaScript 脚本。
- 「避免阻塞:」 将计算密集型、耗时的任务交给 Web Worker 执行。这样,主线程得以解放,可以持续响应用户交互、平滑地更新 UI,保持应用的流畅性。
- 「并行计算:」 利用多核 CPU 的能力,实现真正的并行处理,提升复杂任务的执行效率。
- 「隔离环境:」 Worker 运行在隔离的全局上下文中,与主线程和其他 Worker 互不干扰,避免了直接的变量访问冲突(需要通过消息传递通信)。
Web Worker API
一个 worker 是使用一个构造函数创建的一个对象(例如 Worker())运行一个命名的 JavaScript 文件——这个文件包含将在 worker 线程中运行的代码; worker 运行在另一个全局上下文中,不同于当前的window。因此,在 Worker 内通过 window 获取全局作用域(而不是self)将返回错误。
在专用 worker 的情况下,DedicatedWorkerGlobalScope 对象代表了 worker 的上下文(专用 worker 是指标准 worker 仅在单一脚本中被使用;共享 worker 的上下文是 SharedWorkerGlobalScope 对象)。一个专用 worker 仅能被首次生成它的脚本使用,而共享 worker 可以同时被多个脚本使用。
❝备注: 参见 Web Worker API 落地页以获取 worker 的参考文档和更多指引。 在 worker 线程中你可以运行任何你喜欢的代码,不过有一些例外情况。比如:在 worker 内,不能直接操作 DOM 节点,也不能使用 window 对象的默认方法和属性。但是你可以使用大量 window 对象之下的东西,包括 WebSockets,以及 IndexedDB 等数据存储机制。查看 Web Worker 可以使用的函数和类获取详情。
❞
workers 和主线程间的数据传递通过这样的消息机制进行——双方都使用 postMessage() 方法发送各自的消息,使用 onmessage 事件处理函数来响应消息(消息被包含在 message 事件的 data 属性中)。这个过程中数据并不是被共享而是被复制。
只要运行在同源的父页面中,worker 可以依次生成新的 worker;并且可以使用 XMLHttpRequest 进行网络 I/O,但是 XMLHttpRequest 的 responseXML 和 channel 属性总会返回 null。
点赞、在看!谢谢关注👇