Как вызвать общий метод из приложения реагирования и веб-работника - PullRequest
0 голосов
/ 01 октября 2018

Как я могу сослаться на служебный класс как в приложении React, так и в веб-работнике?

Вот простейшее create-реакции-приложение , которое демонстрирует мою основную проблему.Сам код веб-работника работает нормально, у него просто нет доступа к классу Util.

App.js

import React, { Component } from 'react';
import './App.css';
import Util from './Util.js'
import worker from './Util.worker.js';
import WebWorker from './WebWorker.js';

export default class App extends Component {
    constructor(props) {
        super(props);
        this.util = new Util();
        this.state = { something: "" };
    }
    componentDidMount() {
        this.worker = new WebWorker(worker);
        this.worker.addEventListener('message', e => {
            this.setState({ something: e.data })
        });
    }
    render() {
        return (
            <div className="App">
                <p onClick={e => this.randomHandler()}>{this.util.DoSomething("hello")}</p>
                <p>{this.state.something}</p>
            </div>
        );
    }
    randomHandler() {
        console.log("err")
        this.worker.postMessage(["cool"]);
    }
}

Util.js

export default class Util {
    DoSomething(x) {
        return this.AnotherMethod(x) + "!";
    }
    AnotherMethod(x) {
        return x;
    }
}

WebWorker.js

export default class WebWorker {
    constructor(worker) {
        const code = worker.toString();
        const blob = new Blob(['(' + code + ')()']);
        return new Worker(URL.createObjectURL(blob));
    }
}

Util.worker.js

export default () => {
    self.addEventListener('message', function(e) { // eslint-disable-line no-restricted-globals
        postMessage("How do I call Util.DoSomething() here?");
    }, false);
}

Вот что я хочу сделать.

var util = new Util();
postMessage(util.DoSomething(e.data));

Обычно веб-работниксоздается в пути к файлу, но это плохо работает с React из-за способа компиляции приложения.Вот почему несколько источников рекомендовали сериализовать метод и динамически создавать работника из этого (что я и делаю).

Я попытался передать как сериализованные экземпляры класса, так и сам класс самому работнику,но это не сработало (и это кажется хакерским).

Я также пытался импортировать класс Util в веб-рабочий, но я просто получаю ошибки ссылок, потому что класс WebWorker не обрабатывает импорт.

Может кто-то с опытом в этой областиукажите, что я делаю не так?

1 Ответ

0 голосов
/ 06 октября 2018

К сожалению, ответ состоял в том, чтобы извлечь конфиги из приложения Create React.Как только этот запрос на получение объединен, нам не нужно это делать.

Выполнить эти команды.Обратите внимание, что команда eject необратима.

npm run eject
npm install thread-loader
npm install worker-loader

Добавьте это к webpack.config (dev и prod) в разделе module> rules> oneOf.

{
  test: /\.worker\.(js|jsx|mjs)$/,
  include: paths.appSrc,
  use: [
    require.resolve('worker-loader'),
    // This loader parallelizes code compilation, it is optional but
    // improves compile time on larger projects
    require.resolve('thread-loader'),
    {
      loader: require.resolve('babel-loader'),
      options: {
        // @remove-on-eject-begin
        babelrc: false,
        presets: [require.resolve('babel-preset-react-app')],
        // @remove-on-eject-end
        // This is a feature of `babel-loader` for webpack (not Babel itself).
        // It enables caching results in ./node_modules/.cache/babel-loader/
        // directory for faster rebuilds.
        cacheDirectory: true,
        highlightCode: true,
      },
    },
  ],
},

Then Util.worker.js становится таким:

import Util from './Util.js'

self.addEventListener('message', function(e) {
    var util = new Util();
    self.postMessage(util.DoSomething(e.data)); 
}, false);

И App.js становится таким:

import React, { Component } from 'react';
import './App.css';
import Util from './Util.js'
import Worker from './Util.worker.js';

export default class App extends Component {
    constructor(props) {
        super(props);
        this.util = new Util();
        this.state = { something: "" };
    }
    componentDidMount() {
        this.worker = new Worker();
        this.worker.onmessage = e => {
            console.warn(e.data);
            this.setState({ something: e.data });
        }
    }
    render() {
        return (
            <div className="App">
                <p onClick={e => this.randomHandler()}>{this.util.DoSomething("hello")}</p>
                <p>{this.state.something}</p>
            </div>
        );
    }
    randomHandler() {
        console.log("err")
        this.worker.postMessage("cool");
    }
}
...