Creating a web worker inside React

后端 未结 3 1272
无人及你
无人及你 2020-12-15 09:48

I have a React app created with create-react-app, not ejected. I\'m trying to use web workers. I\'ve tried the worker-loader package (https://github.com/webpack-contrib/work

相关标签:
3条回答
  • 2020-12-15 10:04

    Yes, it is possible to use custom webpack config through using custom-react-scripts.

    To use custom-react-scripts in your existing create-react-app project, as explained in this issue, what you need to do is:

    • Remove react-scripts from package.json:

      "devDependencies": {
          "react-scripts": "0.6.1"
      },
      
    • Run npm install --save-dev *your-custom-react-scripts*

    For a more detailed explanation, have a look at @kitze's article and his own custom-react-scripts, that include built-in support for features like:

    • Decorators
    • babel-preset-stage-0
    • Less
    • Sass
    • CSS modules
    • Sass modules
    • Less modules
    • Stylus modules
    0 讨论(0)
  • 2020-12-15 10:09

    Complimenting dnmh's answer, this comment in the github issue works perfect if you are experiencing problems with "this", "self", "window" subjects...

    In my case following solved all my troubles:

    You don't need to touch this file, just keep it.

    //WebWorkerEnabler.js
    export default class WebWorkerEnabler {
        constructor(worker) {
             let code = worker.toString();
             code = code.substring(code.indexOf("{") + 1, code.lastIndexOf("}"));
    
             const blob = new Blob([code], { type: "application/javascript" });
             return new Worker(URL.createObjectURL(blob));
        }
    }
    

    This is where you run your background tasks

    // WebWorker.js
    export default function WebWorker(args) {
        let onmessage = e => { // eslint-disable-line no-unused-vars
             // THIS IS THE PLACE YOU EMBED YOUR CODE THAT WILL RUN IN BACKGROUND        
             postMessage("Response");
        };
    }
    

    And here is the connection of WebWorker with the rest of your code. You send and receive data to WebWorker from below componentDidMountfunction.

    //BackgroundTaskRunner.js
    import * as React from 'react';
    import WebWorkerEnabler from './WebWorkerEnabler.js';
    import WebWorker from './WebWorker.js';
    const workerInstance = new WebWorkerEnabler(WebWorker);
    export default class BackgroundTaskRunner extends React.Component {
        componentDidMount(){
            workerInstance.addEventListener("message", e => {
                console.log("Received response:");
                console.log(e.data);
            }, false);
            workerInstance.postMessage("bar");
        }
        render() {
            return (
                    <React.Fragment>
                        {"DEFAULT TEXT"}
                    </React.Fragment>
            );
        }
    }
    
    0 讨论(0)
  • 2020-12-15 10:14

    As I've written in the EDIT of my question above, I've found the solution here: https://github.com/facebookincubator/create-react-app/issues/1277

    This is a working example:

    // worker.js
    const workercode = () => {
    
        self.onmessage = function(e) {
            console.log('Message received from main script');
            var workerResult = 'Received from main: ' + (e.data);
            console.log('Posting message back to main script');
            self.postMessage(workerResult);
        }
    };
    
    let code = workercode.toString();
    code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}"));
    
    const blob = new Blob([code], {type: "application/javascript"});
    const worker_script = URL.createObjectURL(blob);
    
    module.exports = worker_script;
    

    Then, in the file that needs to use the web worker:

    import worker_script from './worker';
    var myWorker = new Worker(worker_script);
    
    myWorker.onmessage = (m) => {
        console.log("msg from worker: ", m.data);
    };
    myWorker.postMessage('im from main');
    
    0 讨论(0)
提交回复
热议问题