如果操作依赖于Redux中的另一个异步操作,我该怎么办?

时间:2016-03-02 09:21:41

标签: javascript reactjs redux

对不起我的英语,我希望你能理解我。

我使用redux-thunk进行异步操作。

// actionA.js
export function actionA() {
  return fetch('api call')
           .then((data) => ({
             type: 'actionA',
             data: data
           }))
}

// reducer.js
export function reducer(state, action) {
  ...
  if(action.type === 'actionA') {
    return {
      ...,
      dataA: action.data,
      ...
    };
  }
}

// actionB.js
export function actionB() {
  return (dispatch, getState) => {
    if(!getState().dataA) {
      dispatch(actionA());
    }
    doSomethingWithDataA(getState().dataA);
  };
}

在某些情况下,我只需要在不派遣actionA的情况下发送actionB。但是当我发送actionB时,actionB将使用dataA,而dataA则由actionA创建。因此,在actionB中,我会检查dataA中是否有Store,如果没有,我会先发送actionA。但actionA是异步操作,actionA完成时无法获取。 那么如何处理这个问题呢?

2 个答案:

答案 0 :(得分:3)

一般来说,您希望在dataA准备就绪并且actionB发生时执行某些操作。您可以使用middleware

执行此操作
function myMiddleware() {
    return store => next => action => {
        const dataA = store.getState().dataA;
        if(store.getState().dataA && action.type === 'actionB') {
            doSomethingWithDataA(dataA);
        }
    };
}

然后你的actionB变成了以下

function lazyFetchDataA() {
    return (dispatch, getState) => {
        if(!getState().dataA) {
            return dispatch(actionA());
        } else {
            return Promise.resolve();
        }
    }
}

export function actionB() {
    return (dispatch, getState) => {
       lazyFetchDataA().then(() => dispatch({type: 'actionB'}))
    }   
}

看起来很难,但是现在你在适当的地方有很少的代码可以处理你的事情。

如果您提供有关doSomethingWithDataA的更多信息,可能您不必做这么难的事情,我会给出更好的答案。

答案 1 :(得分:0)

这种方法可能有所帮助,请注意我将使用fetch polyfill返回aysnc请求的承诺。

function actionA(dataA) {
  return {
    type: 'actionA',
    data: dataA
  };
}


export function actionB() {
  return (dispatch, getState) => {
    if(!getState().dataA) {
      return fetch('api call')
          .then((data) => {
            dispatch(actionA(data))
          })
          .catch((error) => {// handle error})
    }
    return doSomethingWithDataA(getState().dataA);
  }
}