标准答案
- Web Worker 可以把耗时 JavaScript 放到独立线程执行,避免阻塞主线程的输入响应、布局和渲染。
- 它适合 CPU 密集型任务,例如大数组计算、图片处理、复杂解析、加密压缩、离线索引构建。它不适合替代普通网络并发,也不适合很小且频繁的同步任务。
- Worker 不能直接访问 DOM,也不能直接共享主线程里的普通对象引用。主线程和 Worker 通过 postMessage 异步通信。
- 传递数据默认使用结构化克隆。ArrayBuffer 这类对象可以通过 transfer 转移所有权,减少大数据复制成本。Worker 也有创建成本、通信成本、打包路径和兼容性边界。
题目解析
Worker 解决的是主线程被长任务占满的问题,不是让计算本身免费变快。任务太小或消息太频繁时,通信和序列化成本可能超过收益。
主线程和 Worker 的数据边界很重要。DOM、函数、闭包上下文不能直接传过去,能传的对象也要符合结构化克隆规则。
Worker 适合任务型异步计算。需要持续共享内存的高级场景可以了解 SharedArrayBuffer 和 Atomics,但它们有更高的安全和工程前提。
代码示例
下面示例展示主线程发送任务、Worker 返回结果,以及 ArrayBuffer 转移所有权。
JavaScript
// main.js
const worker = new Worker(new URL('./sum-worker.js', globalThis._importMeta_.url), {
type: 'module'
})
worker.onmessage = (event) => {
console.log('sum:', event.data.sum)
}
const numbers = new Uint32Array([1, 2, 3, 4])
worker.postMessage({ buffer: numbers.buffer }, [numbers.buffer])
// sum-worker.js
self.onmessage = (event) => {
const numbers = new Uint32Array(event.data.buffer)
const sum = numbers.reduce((total, item) => total + item, 0)
self.postMessage({ sum })
}常见误区
- 在 Worker 中直接访问 document 或 window DOM。
- 频繁传输大对象但不用 Transferable,造成复制成本过高。
- 把 Worker 当成网络请求并发工具,而不是计算线程工具。