Web Workers

Web worker 允许您将一些工作交给 JavaScript 主线程之外去执行,这适合一些大量的计算和后台工作。

在主线程和工作线程之间移动数据会带来与通信相关的开销。这种拆分还提供了隔离,迫使 worker 只关注逻辑,而无法直接操作用户界面。

worker 具有广泛的使用价值。像 parallel-webpack 这样的工具,其底层就是使用 worker-farm 来并行执行 Webpack 的。

正如构建目标章节中所讨论的,Webpack 允许您将应用程序构建放在 worker 中执行。为了更好地了解 Web worker,您将学习如何使用 worker-loader 构建一个小型 worker 。

由于 SharedArrayBuffer 等技术,将来可能在主线程和 worker 之间共享数据将会更加的容易。

设置 worker-loader

首先,将 worker-loader 安装到项目中:

npm install worker-loader --save-dev

您可以将 loader 的定义写入 Webpack 配置中,为了方便演示,这里我们通过内联的方式使用 loader。详细的配置方法,请参阅 “使用 loader”一章。

设置 Worker

一个 worker 必须要做两件事:接收消息并做出响应。在这两个动作之间,它可以执行计算。在这个例子中,您接受并拼接一些文本数据,然后将其发送出去:

src/worker.js

self.onmessage = ({ data: { text } }) => {
  self.postMessage({ text: text + text });
};

设置主线程

主线程必须要实例化 worker,然后与之通信。除了主线程拥有控制权以外,写法上大致相同:

src/component.js

import Worker from "worker-loader!./worker";

export default () => {
  const element = document.createElement("h1");
  const worker = new Worker();
  const state = { text: "foo" };

  worker.addEventListener("message", ({ data: { text } }) => {
    state.text = text;
    element.innerHTML = text;
  });

  element.innerHTML = state.text;
  element.onclick = () => worker.postMessage({ text: state.text });

  return element;
};

你有这两个设置后,worker 应该就可以工作了。当您单击文本时,worker 完成了计算就会改变应用程序的状态。为了演示 worker 的异步性质,您可以尝试在上面的代码中添加延迟并查看会发生什么。

webworkify-webpackworker-loader 的替代品。它允许您将一些常规的 JavaScript 模块用作 worker,同时避免显示地使用 self 关键字。另外,webpack-worker 也值得一看。

总结

需要注意的关键是 worker 无法访问 DOM。您可以在 worker 中执行计算和查询,但不能直接操作用户界面。

回顾一下:

  • Web worker 允许您将工作推出浏览器的主线程。如果性能成为问题,这种分离是有价值的。
  • Web worker 无法操纵 DOM。相反,最好将它们用于较长的计算和网络请求。
  • Web worker 提供的隔离具备一定的架构优势。它迫使程序员留在特定的沙箱中。
  • 与 Web worker 进行通信会产生开销,使其不太实用。随着规范的发展,这可能会在未来发生变化。

您将在下一章中了解国际化。

用户头像
登录后发表评论