HTML本身不支持多线程,真正实现多线程的只有Web Workers;卡顿主因是错误使用:频繁大量postMessage、Worker内同步密集计算、主线程轮询等待、过多Worker实例;应使用Transferable对象传参、时间切片处理、requestAnimationFrame更新DOM;DOM操作、轻量IO、未优化第三方库及低端移动端场景不宜用Worker。

HTML 本身不支持多线程,所谓“HTML 多线程”实际是开发者误用或混淆了 Web Workers、setTimeout、渲染主线程等概念。真正在浏览器中跑多线程逻辑的只有 Web Workers,而它默认不操作 DOM,也不会直接导致页面卡顿——卡顿往往来自错误的使用方式。
为什么用了 Web Workers 还卡顿?
常见误区是以为开了 Worker 就万事大吉,其实卡顿常发生在以下环节:
- 频繁通过
postMessage传递大量数据(如整个ArrayBuffer或深嵌套对象),触发主线程序列化/反序列化阻塞 - Worker 内部做了同步密集计算(比如没分片的
for循环处理 10 万条数据),虽不卡 UI,但消息响应延迟高,用户感知为“没反应” - 在主线程里用
while或长循环等待 Worker 返回,直接冻结渲染 - 创建过多 Worker 实例(>4 个),超出浏览器线程池限制,引发调度竞争和内存压力
Web Workers 正确传参与通信模式
避免卡顿的关键是控制通信频率和数据体积:
- 用
Transferable对象(如ArrayBuffer)传递大数据,避免拷贝:worker.postMessage(arrayBuffer, [arrayBuffer]);
- 不要传
JSON.stringify后的大字符串;优先结构化克隆支持的原生类型(Number、Array、TypedArray) - 对长任务做时间切片:Worker 内用
setTimeout或requestIdleCallback分批处理,再逐批postMessage - 主线程接收消息后,用
requestAnimationFrame更新 DOM,避免强制同步重排
替代方案:什么情况不该用 Web Workers?
不是所有“耗时操作”都适合 Worker,有些反而更慢:
立即学习“前端免费学习笔记(深入)”;
- DOM 操作密集型任务(如批量增删节点)——Worker 无法访问
document,必须回传数据再由主线程渲染,通信开销可能超过收益 - IO 类轻量操作(如读取
localStorage、小文件fetch)——主线程异步已足够,加 Worker 反增启动和上下文切换成本 - 依赖第三方库且未做
ESM拆分的代码(如未打包的moment.js)——Worker 加载失败或报ReferenceError,调试困难 - 移动端低端设备上启用多个 Worker —— 内存紧张时,浏览器可能直接终止 Worker,行为不可控
真正影响卡顿的是主线程是否被长时间占用,而不是“有没有多线程”。Web Workers 是把锅从主线程端走,但端不好照样洒汤。最容易被忽略的一点:Worker 的 importScripts 或 ESM import 如果加载了未压缩的调试版工具库,首次启动延迟可能比计算本身还长。



















