提问人:Th0rgal 提问时间:1/21/2022 最后编辑:vsyncTh0rgal 更新时间:8/9/2022 访问量:5368
将 Web Worker 与 React 和 Webpack 5 一起使用
Using Web Workers with React and Webpack 5
问:
几天来,我一直在尝试将 Web Workers 与 react 一起使用,但遇到了一些问题。
我从使用 webpack 4 的 create-react-app 开始。我可以通过本教程使用Web Worker: https://javascript.plainenglish.io/web-worker-in-react-9b2efafe309c 以这种方式加载WebWorker:
export default class WorkerBuilder extends Worker {
constructor(worker) {
const code = worker.toString();
const blob = new Blob([`(${code})()`]);
return new Worker(URL.createObjectURL(blob));
}
}
不幸的是,我需要使用我的工人 (d3-delaunay) 的库,而 webpack 在我尝试这样做时给了我一个错误(我认为它改变了它的路径)。
我听说过 worker-loader,我了解到它已经被弃用了,因为 Web Worker 导入现在是在 webpack 5 中构建的。
我将我的应用程序更新到 WebPack 5(如 create-react-app wiki 中所述),这并不容易,因为我的很多依赖项都坏了。
但是当我尝试加载我的 WebWorker 时,如此处所述: https://webpack.js.org/guides/web-workers/ 这根本不起作用(没有错误)。
这是我的代码:
console.log("hello");
const worker = new Worker(new URL('./world.worker.js', import.meta.url));
worker.postMessage({
question:
'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
});
worker.onmessage = ({ data: { answer } }) => {
console.log(answer);
};
console.log("world");
还有我的world.worker.js:
import { Delaunay } from "d3-delaunay";
// eslint-disable-next-line import/no-anonymous-default-export
export default () => {
// eslint-disable-next-line no-restricted-globals
self.onmessage = (message) => {
console.log("yolo");
};
};
但我唯一的输出是:
hello
world
我的工人似乎没有工作。
答:
要在 Workers 中使用 ES6 模块,您需要使用以下语法在脚本模式下加载它:
new Worker('worker-path.js', {type: 'module'})
评论
我终于想通了,我遇到了同样的问题。最大的问题是您不应该在 Web Worker 中使用 export default。这是我如何让它工作。
您需要使用 React.useMemo 实例化工作线程。这样,只创建一个工作线程。
const worker = React.useMemo(() => new Worker(new URL('./world.worker.js', import.meta.url)), []);
若要获取响应,需要知道工作器对象何时更新。为此,您可以使用 React.useEffect。
React.useEffect(() => {
worker.onmessage = ({ data: { answer } }) => {
console.log(answer);
return () => worker.terminate();
}
}, [worker]);
最后,您的 world.worker.js 文件有两个问题。第一个是它实际上没有返回任何东西。您需要添加对 postMessage 的调用。第二个问题是我难以弄清楚的问题,是您不应该将函数包装在导出默认值中。我认为这是因为 webpack 会为你包装它。有关正确的 world.worker.js 代码,请参见下文。
import { Delaunay } from "d3-delaunay";
self.onmessage = ({ data: { question } }) => {
postMessage({
answer: 42,
});
};
评论