Web Workers与Service Workers
Web Workers实现浏览器多线程,Service Workers提供离线缓存能力。
Web Workers
基本用法
JavaScript
// 主线程创建Worker
const worker = new Worker('worker.js');
// 发送消息
worker.postMessage({ data: 'hello' });
// 接收消息
worker.onmessage = function(e) {
console.log(e.data);
};
// 错误处理
worker.onerror = function(e) {
console.error(e.message);
};
// 终止Worker
worker.terminate();
Worker脚本
JavaScript
// worker.js
self.onmessage = function(e) {
const result = heavyComputation(e.data);
self.postMessage(result);
};
function heavyComputation(data) {
// 耗时计算
return data * 2;
}
内联Worker
JavaScript
const blob = new Blob([`
self.onmessage = function(e) {
self.postMessage(e.data * 2);
};
`], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
双向通信
JavaScript
// 主线程
worker.postMessage({ type: 'start', data: 100 });
// Worker
self.onmessage = function(e) {
if (e.data.type === 'start') {
// 处理数据
self.postMessage({ type: 'result', data: result });
}
};
Shared Workers
创建与连接
JavaScript
// 多个页面共享同一个Worker
const sharedWorker = new SharedWorker('shared.js');
// 通过port通信
sharedWorker.port.start();
sharedWorker.port.postMessage('hello');
sharedWorker.port.onmessage = function(e) {
console.log(e.data);
};
Shared Worker脚本
JavaScript
// shared.js
const ports = [];
self.onconnect = function(e) {
const port = e.ports[0];
ports.push(port);
port.onmessage = function(e) {
// 广播给所有连接
ports.forEach(p => p.postMessage(e.data));
};
};
Service Workers
注册
JavaScript
// 主线程注册
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('注册成功', reg.scope))
.catch(err => console.error('注册失败', err));
}
生命周期
| 状态 | 说明 |
|---|---|
| installing | 正在安装 |
| installed | 安装完成,等待激活 |
| activating | 正在激活 |
| activated | 激活完成,可控制页面 |
| redundant | 废弃 |
Service Worker脚本
JavaScript
// sw.js
// 安装事件 - 缓存静态资源
self.addEventListener('install', function(e) {
e.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll([
'/',
'/style.css',
'/app.js'
]);
})
);
});
// 激活事件 - 清理旧缓存
self.addEventListener('activate', function(e) {
e.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.filter(k => k !== 'v1')
.map(k => caches.delete(k))
);
})
);
});
// 请求拦截 - 缓存策略
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request)
.then(response => response || fetch(e.request))
);
});
缓存策略
Cache First
JavaScript
// 优先缓存,无则请求
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(response => {
return response || fetch(e.request);
})
);
});
Network First
JavaScript
// 优先网络,失败则缓存
self.addEventListener('fetch', function(e) {
e.respondWith(
fetch(e.request).catch(() => caches.match(e.request))
);
});
Stale While Revalidate
JavaScript
// 返回缓存同时更新
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(response => {
const fetchPromise = fetch(e.request).then(res => {
caches.open('v1').then(cache => cache.put(e.request, res));
return res;
});
return response || fetchPromise;
})
);
});
注意事项
- Worker不能直接操作DOM,必须通过消息通信
- Service Worker只能运行在HTTPS或localhost
- Service Worker作用域默认是注册路径及其子路径
- Worker中可使用importScripts()加载脚本
要点总结
- Web Workers用于CPU密集型任务,不阻塞主线程
- 主线程与Worker通过postMessage/onmessage通信
- Service Workers提供离线缓存和请求拦截能力
- 缓存策略包括Cache First、Network First、Stale While Revalidate
- Service Worker生命周期:install -> activate -> fetch
存放路径:articles/JS/进阶/浏览器与DOM高级/Web Workers与Service Workers.md
📝 发现内容有误?点击此处直接编辑