Web Workeropen in new window 可以实现将复杂、耗时的计算从 JavaScript 的主执行进程中抽离出来,以后台任务的形式运行,避免影响主执行进程。Web Worker 无法操作 DOM 元素。
在前面设置构建输出目标一章中我们介绍过构建 Web Worker 的配置,这里我们介绍一下具体的使用方法。
添加一个 worker
一个 Worker 需要关注两件事情,一个是接收消息,一个是响应消息。在这之前,Worker 进行计算处理。
src/worker.js
self.onmessage = ({ data: { text } }) => {
self.postMessage({ text: text + text });
};
2
3
添加一个宿主
宿主需要初始化 Worker 并与 Worker 进行通信。
src/component.js
export default (text = HELLO) => {
const element = document.createElement('h1');
const worker = new Worker(new URL('./worker.js', import.meta.url));
const state = { text };
worker.addEventListener('message', ({ data: { text } }) => {
state.text = text;
element.innerHTML = text;
});
element.innerHTML = state.text;
element.onclick = () => worker.postMessage({ text: state.text });
return element;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
完成这两步以后,我们就可以实现按钮的文案来自于 worker 计算的结果了。我们还可以将 worker 的响应改成异步的形式,加一些延时,看看按钮的变化。
数据共享
考虑到 Worker 与宿主间通信过程中数据序列化的开销,我们可以通过 Transferable objectsopen in new window 来降低序列化的开销,同时还可以考虑使用 SharedArrayBufferopen in new window 来共享数据。
其他选择
在 Webpack 5 之前,我们可以使用 worker-loaderopen in new window 来构建 Worker,现在依然可以使用,worker-loader 提供了更加细粒度的配置。
借助于 workerize-loaderopen in new window 和 worker-pluginopen in new window 我们可以想普通 JavaScript 模块一样定义 Worker,同时还可以避免使用上面样例中 self
。
threads.jsopen in new window 提供了功能更加丰富,也更加复杂的解决方案。Thread.js 提供了可观察对象、线程池等特性。我们可以通过 threads-pluginopen in new window 将其与 Webpack 结合起来。
总结
Web Worker 可以将复杂的计算等任务从 JavaScript 主执行进程中剥离出来,作为后台任务运行。Worker 无法直接操作用户 UI。
Web Worker 的通信开销比较大,不过随着上面介绍的一些技术的发展,这个问题将会得到改善。
关注微信公众号,获取最新推送~
加微信,深入交流~