Web Workers怎么帮网页渲染不卡顿?

你有没有遇到过这样的情况:ref="/tag/88/" style="color:#EB6E00;font-weight:bold;">网页上点个按钮,页面突然‘僵住’半秒,滚动也变慢,甚至右上角的加载圈转个不停?尤其在处理大量数据、生成复杂图表或实时解析大文件时,这种卡顿特别明显。

主线程太忙,页面就‘装死’

浏览器里,HTML 渲染、用户交互(比如点击、滚动)、JavaScript 执行,全挤在同一个线程——主线程。一旦 JS 脚本干起了耗时活儿(比如遍历 10 万个对象、做图像像素计算、解析几 MB 的 JSON),主线程就被占满,浏览器根本腾不出手去更新界面,用户看到的就是‘假死’。

Web Workers:悄悄干活不打扰

Web Workers 就像给网页配了个后台小助手。它在独立线程里运行 JS,不碰 DOM,也不影响主线程。你可以把重活交给它,算完再把结果‘递’回来,主线程照常响应点击、滚动、动画,丝滑不打折。

举个实在的例子:一个在线 Excel 类工具,用户上传了一个含 5 万行数据的 CSV 文件。如果直接在主线程里逐行解析、校验、转成表格结构,页面立刻卡住;换成 Worker,解析过程完全后台进行,界面上还能显示‘正在处理…(63%)’的进度条,用户可以随时点‘取消’。

动手试试:一个最简 Worker 示例

先新建一个 worker.js 文件:

self.onmessage = function(e) {
const data = e.data;
// 模拟耗时计算
let result = 0;
for (let i = 0; i < data.count; i++) {
result += Math.sqrt(i) * Math.sin(i);
}
self.postMessage({ result });
};

然后在主页面中调用它:

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

worker.onmessage = function(e) {
document.getElementById('result').textContent = '计算完成:' + e.data.result;
};

// 启动计算(不阻塞页面)
worker.postMessage({ count: 1000000 });

// 页面其他操作照常:
document.body.style.backgroundColor = '#f0f9ff'; // 立刻生效

注意几个实际限制

Worker 不能直接操作 DOM,也不能访问 window、document 这些对象——这恰恰是它的优点:避免了多线程对 DOM 的竞争冲突。所有数据传递靠 postMessage,内容会自动序列化(支持 Structured Clone,包括数组、对象、Map、Set,但不支持函数和 DOM 节点)。如果要渲染大量 HTML 片段,可以在 Worker 里拼好字符串或生成虚拟节点数据,再传回主线程由 innerHTMLcreateElement 插入。