简体   繁体   中英

How to use a local class in a Webworker with React?

I'm working on a webworker and want to use a local class. The worker is created and used in a React application with (mostly) standard Webpack setup. This is the essential code:

/* eslint-disable no-restricted-globals */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/* eslint-disable no-eval */

class Executor {
    run(code) {
        let result = "";
        let isError = false;
        try {
            result = eval(code);
            if (typeof result === "object") {
                result = JSON.stringify(result);
            }
        } catch (error) {
            result = error.toString();
            isError = true;
        }

        return [result, isError];
    }
}

export default () => {
    try {
        const executor = new Executor();
    } catch (e) {
        console.log("Webworker startup error: " + e);
    }
};

and when I create the webworker:

public componentDidMount(): void {
    const code = runtime.toString();
    const blob = new Blob(["(" + code + ")()"]);
    this.worker = new Worker(URL.createObjectURL(blob));
    this.worker.onmessage = this.handleWorkerMessages;
}

I get the error:

Webworker startup error: ReferenceError: Executor is not defined

What else is required to make the webworker recognize that class?

I also tried to put the class into an external file and import it from there, however that only changed the error a little:

Webworker startup error: ReferenceError: _ScriptingExecutor__WEBPACK_IMPORTED_MODULE_0__ is not defined

To understand what's going on you have to look at the string which is generated from the imported module (right before it is converted to a Blob). It contains only the default exported code (ie the anonymous function). The class is not included and consequently, when you load the code into your worker it misses the class.

So either do not use a module for the worker code or use the URL to the script and feed that to the worker.

I think it will work if you put the Executor inside the default section.

export default () => {
    class Executor {
        run(code) {
            let result = "";
            let isError = false;
            try {
                result = eval(code);
                if (typeof result === "object") {
                    result = JSON.stringify(result);
                }
            } catch (error) {
                result = error.toString();
                isError = true;
            }

            return [result, isError];
        }
    }

    try {
        const executor = new Executor();
    } catch (e) {
        console.log("Webworker startup error: " + e);
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM