第三方库
workerize
let worker = workerize(`
export function add(a, b) {
// block for half a second to demonstrate asynchronicity
let start = Date.now();
while (Date.now()-start < 500);
return a + b;
}
`);
(async () => {
console.log("3 + 9 = ", await worker.add(3, 9));
console.log("1 + 2 = ", await worker.add(1, 2));
})();
我们也可以使用 workerize-loader 作为 Webpack 插件来加载 Web Worker:
// worker.js
export function expensive(time) {}
// app.js
import worker from "workerize-loader!./worker";
let instance = worker(); // `new` is optional
instance.expensive(1000).then(count => {
console.log(`Ran ${count} loops`);
});
You cannot use Local Storage in service workers. It was decided that service workers should not have access to any synchronous APIs. You can use IndexedDB instead, or communicate with the controlled page using postMessage().
Comlink
Comlink 使 WebWorkers 变得愉快。Comlink 是一个很小的库(1.1kB),它消除了思考 postMessage 的思维障碍,并掩盖了您与工人一起工作的事实。在手机上,尤其是在低端手机上,重要的是保持主线程尽可能空闲,以便它可以快速响应用户交互并提供无垃圾的体验。UI 线程应仅用于 UI 工作。WebWorkers 是一个 Web API,允许您在单独的线程中运行代码。为了与另一个线程通信,WebWorkers 提供了 postMessage API。您可以使用 myWorker.postMessage(someObject)将 JavaScript 对象作为消息发送,从而在 worker 内部触发消息事件。
通过提供 RPC 实现,Comlink 将基于消息的 API 变成了对开发人员更友好的实现:来自一个线程的值可以在另一个线程内使用(反之亦然),就像本地值一样。
Simple App
- main.js
import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs";
async function init() {
const worker = new Worker("worker.js");
// WebWorkers use `postMessage` and therefore work with Comlink.
const obj = Comlink.wrap(worker);
alert(`Counter: ${await obj.counter}`);
await obj.inc();
alert(`Counter: ${await obj.counter}`);
}
init();
- worker.js
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");
// importScripts("../../../dist/umd/comlink.js");
const obj = {
counter: 0,
inc() {
this.counter++;
}
};
Comlink.expose(obj);
Callback
- main.js
import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs";
// import * as Comlink from "../../../dist/esm/comlink.mjs";
function callback(value) {
alert(`Result: ${value}`);
}
async function init() {
const remoteFunction = Comlink.wrap(new Worker("worker.js"));
await remoteFunction(Comlink.proxy(callback));
}
init();
- worker.js
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");
// importScripts("../../../dist/umd/comlink.js");
async function remoteFunction(cb) {
await cb("A string from a worker");
}
Comlink.expose(remoteFunction);