标准答案

  1. Web Worker 可以把耗时 JavaScript 放到独立线程执行,避免阻塞主线程的输入响应、布局和渲染。
  2. 它适合 CPU 密集型任务,例如大数组计算、图片处理、复杂解析、加密压缩、离线索引构建。它不适合替代普通网络并发,也不适合很小且频繁的同步任务。
  3. Worker 不能直接访问 DOM,也不能直接共享主线程里的普通对象引用。主线程和 Worker 通过 postMessage 异步通信。
  4. 传递数据默认使用结构化克隆。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 当成网络请求并发工具,而不是计算线程工具。

作者信息