Web Worker 的作用与场景
Web Worker 实现多线程及其使用场景
问题
Web Worker 是什么?有哪些使用场景?如何使用?
解答
Web Worker 让 JavaScript 可以在后台线程运行脚本,不阻塞主线程,避免页面卡顿。
基本用法
主线程 (main.js)
// 创建 Worker
const worker = new Worker('worker.js');
// 发送消息给 Worker
worker.postMessage({ type: 'calculate', data: [1, 2, 3, 4, 5] });
// 接收 Worker 返回的消息
worker.onmessage = (event) => {
console.log('计算结果:', event.data);
};
// 错误处理
worker.onerror = (error) => {
console.error('Worker 错误:', error.message);
};
// 终止 Worker
// worker.terminate();
Worker 线程 (worker.js)
// 接收主线程消息
self.onmessage = (event) => {
const { type, data } = event.data;
if (type === 'calculate') {
// 执行耗时计算
const result = data.reduce((sum, num) => sum + num, 0);
// 返回结果给主线程
self.postMessage(result);
}
};
实际场景:大数据处理
// worker.js - 处理大量数据排序
self.onmessage = (event) => {
const data = event.data;
// 耗时的排序操作
const sorted = data.sort((a, b) => a - b);
self.postMessage(sorted);
};
// main.js
const worker = new Worker('worker.js');
const largeArray = Array.from({ length: 1000000 }, () => Math.random());
worker.postMessage(largeArray);
worker.onmessage = (e) => {
console.log('排序完成', e.data.slice(0, 10));
};
实际场景:图片处理
// worker.js - 图片灰度处理
self.onmessage = (event) => {
const imageData = event.data;
const data = imageData.data;
// 遍历每个像素,转为灰度
for (let i = 0; i < data.length; i += 4) {
const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
data[i] = gray; // R
data[i + 1] = gray; // G
data[i + 2] = gray; // B
}
self.postMessage(imageData);
};
使用 Blob 创建内联 Worker
// 不需要单独的 worker.js 文件
const workerCode = `
self.onmessage = (e) => {
const result = e.data * 2;
self.postMessage(result);
};
`;
const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.postMessage(10);
worker.onmessage = (e) => console.log(e.data); // 20
SharedWorker:多页面共享
// shared-worker.js
const connections = [];
self.onconnect = (event) => {
const port = event.ports[0];
connections.push(port);
port.onmessage = (e) => {
// 广播给所有连接的页面
connections.forEach(p => p.postMessage(e.data));
};
};
// 页面中使用
const shared = new SharedWorker('shared-worker.js');
shared.port.start();
shared.port.postMessage('hello');
shared.port.onmessage = (e) => console.log(e.data);
Worker 的限制
// Worker 中不能访问
// - DOM (document, window)
// - parent 对象
// Worker 中可以使用
// - navigator, location (部分)
// - setTimeout, setInterval
// - fetch, XMLHttpRequest
// - IndexedDB
// - importScripts() 加载脚本
// worker.js
importScripts('utils.js', 'helper.js');
关键点
- 不阻塞主线程:耗时任务放 Worker,保持 UI 流畅
- 通信靠消息:postMessage 发送,onmessage 接收,数据是拷贝的
- 无法访问 DOM:Worker 运行在独立上下文,不能操作页面
- 适用场景:大数据处理、复杂计算、图片/音视频处理、加密解密
- SharedWorker:可被多个页面共享,适合跨标签页通信
目录