首页 文章

使用Redux的Web-Worker承诺

提问于
浏览
1

我的设置是:Webpack,React,Redux(包括redux-thunk) .

我正在努力在我的 mouseMove eventListener中集成Web worker . 当用户在绘图应用程序中绘制时,需要找出与'group selection' rect发生冲突的元素 .

对web-worker的调用将是异步的,因此,在action-creator函数中,我试图提出一个promise,在解决后,调用有效负载创建func(resolve),如下所示:

ACTION CREATOR:

export const groupSelectionPayload = ( a, b, c ) => {
    let something = doSomething( a, b );
    return( new Promise( function( resolve, reject ){
        let selectedElements = getSelectedElements( something, c );
        // Im not sure about the below condition,
        //  which I am using to call either resolve / reject funcs,
        //  is there a better way to handle this?
        if( selectedElements !== undefined ){
            resolve( something );
        } else {
            reject();
        }
    }));
};

// when promise resolves, we return the action to dispatch
const resolve = function( rectCoOrd ){
    return ({
        type : CREATE_GROUP_SELECTION_RECT,
        svgPayload : {
            curToolbarCtrlSelection : {
                ctrlName : "grpSelect",
                props : {
                    pos : {
                        x : rectCoOrd[ 0 ],
                        y : rectCoOrd[ 1 ],
                        w : rectCoOrd[ 2 ],
                        h : rectCoOrd[ 3 ]
                    }
                }
            }
        }
    });
};

// func posts message to web-worker
const getSelectedElements = ( something, c ) => {
    worker_handler.postMessage( iMap({
        type : "grpSelect",
    }));
};

我使用Redux-thunk进行异步,但是,我收到错误: Error: Actions must be plain objects. Use custom middleware for async actions. 后面跟着: uncaught exception : undefined

我做错了什么,是否有一种更合理的方式来处理上面讨论的场景?

Edit: 我需要安装我拥有的redux-promise中间件 .

const store = createStore( reducer, composeEnhancer( applyMiddleware( thunk, promiseMiddleware )));

...已解决 Actions must be plain objects ... 错误 . 但是,我仍然收到 uncaught exception : undefined 错误 .

1 回答

  • 1

    好吧,我想你的动作创作者应该是这样的:

    export const groupSelectionPayload = ( a, b, c ) => dispatch => {
      //do some async stuff like so:
    
      new Promise((res, rej) => { … })
        .then(data => dispatch({type: 'success', payload: { data }}))
        .catch(error => dispatch({type: 'error', payload: { error }}))
    }
    

    Redux thunk将使用dispatch作为参数调用创建者返回的方法 . 因此,在该方法中,您可以在完成异步内容时,在执行之前或之前调度其他操作 .

    另外,redux thunk将返回动作创建者提供的函数的值 . 所以也可以:

    const someAction = id => dispatch => new Promise((res, rej) => {
      const result = something(id);
      if (result !== null) {
        dispatch({type: 'success', payload: { result }})
        res(result);
      } else { … }
    
    });
    

    在你的组件中:

    this.props.action(<id>).then(/*getting fancy here, update State or something*/);
    

    但是当你处理webWorker时,我认为中间件是放置代码的更好的地方:

    const customMiddleware = store => {
      //create and connect to the worker here
      const worker = …
      worker.onmessage = msg => store.dispatch({type: 'workermsg', payload: {msg}});
      return next => action => {
        if(action.type !== 'posttoworker') return next(action)
        worker.postMessage(action.payload.msg)
      }
    }
    

    我没有太在意 Worker 代码,只是关于这个想法,使用中间作为 Worker 的api ......

相关问题