Web Worker:解决前端计算阻塞问题

浏览器中的 JavaScript 通常运行在主线程上。页面渲染、用户点击、输入响应和脚本执行都会受到主线程状态的影响。如果一段计算运行时间太长,页面就可能出现卡顿,甚至暂时无法响应操作。

Web Worker 提供了一个独立的后台线程,可以把不依赖 DOM 的计算任务交给它处理。主线程负责页面交互,Worker 负责数据计算,计算结束后再把结果传回来。

一个简单的使用方式

主线程创建 Worker,并通过 postMessage 发送数据:

const worker = new Worker('./worker.js')

worker.postMessage({
type: 'calculate',
data: largeList
})

worker.onmessage = (event) => {
console.log('计算结果:', event.data)
worker.terminate()
}

worker.js 中接收数据,完成计算后返回结果:

self.onmessage = (event) => {
const { type, data } = event.data

if (type === 'calculate') {
const result = data.map((item) => item.value * 2)
self.postMessage(result)
}
}

主线程和 Worker 之间不能直接共享普通变量,而是通过消息通信。数据会经过结构化克隆,数据量很大时也要考虑传输成本。

适合什么场景

Worker 更适合处理纯数据和计算密集型任务,例如:

  • 大数组排序、筛选和转换
  • 文件解析
  • 图片或音频数据处理
  • 加密计算
  • 大量数据统计

Worker 不能直接操作页面 DOM,也不能直接访问主线程中的变量。如果任务需要频繁更新页面,通常应该让 Worker 负责计算,主线程负责根据结果更新 UI。

不要为了使用而使用

Worker 也有创建线程、消息通信和数据复制的成本。如果只是一个很小的计算,直接在主线程中执行反而更简单。只有当计算本身足够耗时,已经影响到页面交互时,才值得引入 Worker。

我的理解是,Web Worker 并不是让前端“拥有了无限算力”,而是把不同类型的工作分配到更合适的线程中。使用前最好先通过性能面板确认瓶颈,再决定是否需要拆分任务。