1.0.4 • Published 4 years ago

ray-worker v1.0.4

Weekly downloads
-
License
MIT
Repository
-
Last release
4 years ago

ray-worker

install

npm i --save ray-worker

props

paramstypedefaultdescr
childrennode or func-内容区,自定义 worker接收展示, func: (workerState) => {}
workerResstring or func-创建worker,当为 string时,表示 worker 路径,当为 function时,可将整个worker包装进一个 function进行创建
optionsobject-worker参数,如: { name: 'myworker' }
workerobject-自定义 Worker 实例,如:采用 worker-loader加载worker时,可创建后传递
parserfunc-data 解析器,解析从 Worker 中收到的message
onMessagefunc-处理从 worker 接收到的消息数据
onErrorfunc-worker错误处理
serializerfuncv => v序列化或者处理发送至 worker 的数据, 在 手动调用 postMessage 之后处理data
forceMessageboolfalse强制接收消息,即:即使dom没有加载完成,也接收 worker 消息
preventWorkerbool-不给 children 注入 worker 的属性,当采用 ref 方式处理worker时,可以设置为 true

注意: 默认情况下,只有 dom 加载完成之后,才接收 worker 中的消息,如果 设置 forceMessagetrue 时,则只要 worker 创建,则可接收。

workerstate

paramstypedefaultdescr
messagesarray[]从worker中接收到的所有的数据日志,{ data, date }
errorsarray[]从worker中接收到的所有的错误信息,{ error, date }
dataanyundefined从worker中接收到的数据,最新数据
erroranyundefined从worker中接收到的错误信息,最新错误信息
updateTimeDateundefined更新日期,worker发送数据或错误时的当前日期
lastPostTimeDateundefined最后一次发送向worker数据的日期
postMessagefunc: (data) => {}-向 worker 发送消息

注意: 默认在 componentWillUnmount 中执行了 worker.terminate,同时向 worker 发送了 type = 'CLOSED'的数据,用于告知worker执行关闭。如果需要关闭 worker,则自行在worker中进行处理,如:

worker.js

self.addEventListener('message', e => {
  if (!e) {
    return;
  }
  let data = e.data;

  if (data && data.type === 'CLOSED'){
    self.close(); // Terminates the worker.
  }
  console.log('Received msg from UI:', data);
  postMessage(data + random());
});

USAGE

  • basic

app.js

import React, { Component } from 'react';
import RWorker from 'ray-worker';
import Button from './Button';

/**
 * 采用直接导入 worker 的方式
 *
 * @class WorkerDemo
 * @extends {Component}
 */
class WorkerDemo extends Component {
  render() {
    return (
      <RWorker workerRes="/demo1.js">
        {({ data, error, postMessage, updatedAt, lastPostTime }) => (
          <div className="worker-msg-box">
            {data && (
              <div>
                <strong>[采用普通loader进行]Received some data:</strong>
                <pre>{JSON.stringify(data, null, 2)}</pre>
              </div>
            )}
            <Button updatedAt={updatedAt} lastPostTime={lastPostTime} postMessage={postMessage} />
          </div>
        )}
      </RWorker>
    );
  }
}

WorkerDemo.propTypes = {};

export default WorkerDemo;

demo1.js (worker)

function random() {
  const i = Math.random() * 100 + 1;
  return `ilex- ${parseInt(i)}`;
}

self.addEventListener('message', e => {
  if (!e) {
    return;
  }
  let data = e.data;

  console.log('Received msg from UI:', data);

  postMessage(data + random());
});
  • use normal module

将 worker 作为一个 function 进行

app.js

import React, { Component } from 'react';
import RWorker from 'ray-worker';
import Button from './Button';
import demo from './demo';

/**
 * 采用 模块加载的方式
 *
 * @class WorkerDemo
 * @extends {Component}
 */
class WorkerDemo extends Component {
  render() {
    return (
      <RWorker workerRes={demo}>
        {({ data, error, postMessage, updatedAt, lastPostTime }) => (
          <div className="worker-msg-box">
            {data && (
              <div>
                <strong>Received some data:</strong>
                <pre>{JSON.stringify(data, null, 2)}</pre>
              </div>
            )}
            <Button updatedAt={updatedAt} lastPostTime={lastPostTime} postMessage={postMessage} />
          </div>
        )}
      </RWorker>
    );
  }
}

WorkerDemo.propTypes = {};

export default WorkerDemo;

demo.js (worker)

export default () => {
  function random() {
    const i = Math.random() * 100 + 1;
    return `ilex- ${parseInt(i)}`;
  }
  self.addEventListener('message', e => {
    if (!e) {
      return;
    }
    let data = e.data;

    console.log('Received msg from UI:', data);

    postMessage(data + random());
  });
};
  • worker-loader

app.js

import React, { Component } from 'react';
import RWorker from 'ray-worker';
import Button from './Button';
import Worker from './demo.worker.js';

/**
 * 采用 worker loader 方式
 *
 * @class WorkerLoaderDemo
 * @extends {Component}
 */
class WorkerLoaderDemo extends Component {

  constructor(props) {
    super(props);
    this.worker = new Worker();
  }

  render() {
    return (
      <RWorker worker={this.worker}>
        {({ data, error, postMessage, updatedAt, lastPostTime }) => (
          <div className="worker-msg-box">
            {data && (
              <div>
                <strong>[采用worker-loader进行]Received some data:</strong>
                <pre>{JSON.stringify(data, null, 2)}</pre>
              </div>
            )}
            <Button updatedAt={updatedAt} lastPostTime={lastPostTime} postMessage={postMessage} />
          </div>
        )}
      </RWorker>
    );
  }
}

WorkerLoaderDemo.propTypes = {};

export default WorkerLoaderDemo;

demo.worker.js (worker)

worker 中可以采用 es6 模块

import { random } from './_third';

// function random() {
//   const i = Math.random() * 100 + 1;
//   return `ilex- ${parseInt(i)}`;
// }

self.addEventListener('message', e => {
  if (!e) {
    return;
  }
  let data = e.data;

  if (data && data.type === 'CLOSED'){
    self.close(); // Terminates the worker.
  }

  console.log('Received msg from UI:', data);

  postMessage(data + random());
});

扩展

  • DataPane
  • Pending
  • WError

使用datapane, app.js

import React, { Component } from 'react';
import RWorker from 'ray-worker';
import Worker from './inner.worker.js';

const { Pending, DataPane, WError } = RWorker;

/**
 * 采用 worker loader 方式
 *
 * @class WorkerInnerDemo
 * @extends {Component}
 */
class WorkerInnerDemo extends Component {

  constructor(props) {
    super(props);
    this.worker = new Worker();
  }

  render() {
    return (
      <RWorker worker={this.worker}>
        <DataPane>
          {
            (data, workerState) => (
              <div className="worker-msg-box">
                <div>auto data:{data}</div>
                <div className="all-msg">
                  <p>所有数据</p>
                  {JSON.stringify(workerState)}
                </div>
              </div>
            )
          }
        </DataPane>
      </RWorker>
    );
  }
}

WorkerInnerDemo.propTypes = {};

export default WorkerInnerDemo;

inner.worker.js (worker)

import { random } from './_third';

self.addEventListener('message', e => {
  if (!e) {
    return;
  }
  let data = e.data;

  if (data && data.type === 'CLOSED'){
    self.close(); // Terminates the worker.
  }

  console.log('Received msg from UI:', data);
  postMessage(data + random());
});

postMessage(`auto data ${random()}`);

setInterval(() => {
  postMessage(`auto data ${random()}`);
}, 2000);

WorkerPlugin

import React, { Component } from 'react';
import { WorkerPlugin } from 'ray-worker';
import demo from './workers/demo';

/**
 * 采用 worker plugin
 *
 * @class WorkerDemo
 * @extends {Component}
 */
class WorkerDemo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      data: undefined
    };
    this.worker = new WorkerPlugin({
      workerRes: demo,
      onMessage: this.onMessage
    });
  }

  componentWillUnmount() {
    this.worker.destroy();
  }

  onMessage = (data) => {
    this.setState({
      data
    });
  }

  onClick = () => {
    this.worker.postMessage('hello');
  }

  render() {
    const { data } = this.state;
    return (
      <div className="worker-msg-box">
        {data && (
          <div>
            <strong>Received some data:</strong>
            <pre>{JSON.stringify(data, null, 2)}</pre>
          </div>
        )}
        <div className="action-button">
          <button onClick={this.onClick}>发送消息</button>
        </div>
      </div>
    );
  }
}

WorkerDemo.propTypes = {};

export default WorkerDemo;
  • params
{
  workerRes: 'string|func',
  options: 'object',
  worker: 'any',
  parser: 'func',
  onMessage: 'func',
  onStateChange: 'func',
  serializer: 'func',
  onError: 'func'
}
  • methods
postMessage()
getWorkerState()
destroy()

UIWorkerFactory

自行处理 主线程 worker UI

import React, { Component } from 'react';
import { UIWorkerFactory } from 'ray-worker';
import Worker from './workers/inner.worker.js';

/**
 * 采用 worker loader 方式
 *
 * @class NonUIWorkerDemo
 * @extends {Component}
 */
class NonUIWorkerDemo extends Component {

  constructor(props) {
    super(props);
    this.worker = new Worker();
    this.uiWorkerFactory = new UIWorkerFactory({
      worker: this.worker,
      onMessage: this.onMessage,
      onError: this.onError
    });
    this.state = {
      messages: [],
      msg: ''
    };
  }

  onMessage = (msg) => {
    this.setState(prevState => ({
      messages: [
        ...prevState.messages,
        msg
      ],
      msg
    }));
  }

  onError = (err) => {
    console.log(err);
  }

  render() {
    return (
      <div className="worker-msg-box">
        <div>current message:{this.state.msg}</div>
        <div className="all-msg">
          <p>所有数据:</p>
          {JSON.stringify(this.uiWorkerFactory.workerState, null, 2)}
        </div>
      </div>
    );
  }
}

NonUIWorkerDemo.propTypes = {};

export default NonUIWorkerDemo;

注意

children 为function时,参数为 RayWorker 整个 state; 当为 普通react组件时,默认注入 RayWorker 整个state

其它情况,如果要使用 RayWorker state,则可以使用 getWorkerState 方法获取。

import RWorker from 'ray-worker';

const workerState = this.rworkerRef.getWorkerState();

<RWorker ref={node => this.rworkerRef = node}>

Lecense

MIT

1.0.4

4 years ago

1.0.3

5 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago