【问题标题】:Web Worker with imported modules in React在 React 中带有导入模块的 Web Worker
【发布时间】:2020-07-20 10:14:14
【问题描述】:

我正在尝试创建一个 web worker 来防止 React 主线程停止。工人应该阅读图像并做各种事情。

该应用是使用create-react-app 创建的。

目前我有

WebWorker.js

export default class WebWorker {
    constructor(worker) {
        const code = worker.toString();
        const blob = new Blob(['('+code+')()'], {type: "text/javascript"});
        return new Worker(URL.createObjectURL(blob),  {type: 'module'});
    }
}

readimage.worker.js

import Jimp from "jimp";

export default () => {
    self.addEventListener('message', e => { // eslint-disable-line no-restricted-globals
        if (!e) return;
        console.log('Worker reading pixels for url', e.data);
        let data = {};

        Jimp.read(e.data).then(image => {
            // jimp does stuff
            console.log('Worker Finished processing image');
        })

        postMessage(data);
    })
};

然后在我的 React 组件 AppContent.js 我有 从“./workers/WebWorker”导入 WebWorker; 从'./workers/readimage.worker.js'导入readImageWorker;

export default function AppContent() {
    const readWorker = new ReadImageWorker(readImageWorker);
    readWorker.addEventListener('message', event => {
        console.log('returned data', event.data);
        setState(data);
    });

    // callback that is executed onClick from a button component
    const readImageContents = (url) => {
        readWorker.postMessage(url);
        console.log('finished reading pixels');
    };
}

但是当我运行它时,我得到了错误

未捕获的引用错误:jimp__WEBPACK_IMPORTED_MODULE_0___default 未定义

如何将模块正确导入网络工作者?

 

编辑:

根据 Kaiido 的建议,我尝试安装 worker-loader,并将我的 webpack.config.js 编辑为以下内容:

module.exports = {
    module: {
        rules: [
            {
                test: /\.worker\.js$/,
                use: { loader: 'worker-loader' }
            }
        ]
    }
};

但是当我运行它时,我仍然得到错误

未捕获的引用错误:未定义 jimp__WEBPACK_IMPORTED_MODULE_0__

【问题讨论】:

    标签: javascript reactjs web-worker


    【解决方案1】:

    我不太喜欢 React,所以我不知道 module-Worker 是否是最好的方法(也许worker-loader 会是一个更好的解决方案),但关于你得到的最后一个错误,它是因为你在构建 Blob 时没有设置 type

    在这种情况下,它确实很重要,因为它将确定浏览器在将其提供给获取它的 API 时设置的 Content-Type。
    在这里,Firefox 稍微宽松一些,并且以某种方式允许它,但 Chrome 很挑剔,需要您将此 type 选项设置为众多 javascript MIME 类型之一。

    const script_content = `postMessage('running');`;
    
    // this one will fail in Chrome
    const blob1 = new Blob([script_content]); // no type option
    const worker1 = new Worker(URL.createObjectURL(blob1), { type: 'module'});
    worker1.onerror = (evt) => console.log( 'worker-1 failed' );
    worker1.onmessage = (evt) => console.log( 'worker-1', evt.data );
    // this one works in Chrome
    const blob2 = new Blob([script_content], { type: "text/javascript" });
    const worker2 = new Worker(URL.createObjectURL(blob2), { type: 'module'});
    worker2.onerror = (evt) => console.log( 'worker-2 failed' );
    worker2.onmessage = (evt) => console.log( 'worker-2', evt.data );

    但是现在这个错误已经修复了,你会遇到另一个错误,因为 import lib from "libraryname" 格式在浏览器中仍然不受支持,所以你必须将 "libraryname" 更改为你的实际脚本文件的路径,请记住,它将与您的 Worker 的基本 URI 相关,即可能是您的主页的来源。

    【讨论】:

    • 第二个删除了我发布的相同错误中的 1 个。但我仍然得到那个错误。 (铬)
    • @cclloyd 我不确定你的评论是否理解。你能更清楚你得到什么错误吗?
    • 对不起,不同的错误。如果我在构造函数中没有任何类型,我会得到一个。 Uncaught ReferenceError: jimp__WEBPACK_IMPORTED_MODULE_0___default is not defined,source 引用了我在 worker 函数中调用 Jimp 的那一行。
    • 如我所说,只能回答原生Worker错误。一件事是浏览器仍然不支持您的路径import Jimp from "jimp" 格式,您必须在此处使用绝对URL (import Jimp from "https://yoursite/assets/jimp.js")。但是既然你使用的是 webpack,为什么不使用那个worker-loader 模块呢?
    • 我尝试添加 worker-loader 但仍然出现错误。编辑了我的帖子以反映更改。
    猜你喜欢
    • 2019-07-28
    • 1970-01-01
    • 2021-11-09
    • 2019-10-30
    • 2020-01-06
    • 2019-05-10
    • 2018-04-02
    • 1970-01-01
    • 2020-11-11
    相关资源
    最近更新 更多