【问题标题】:How to know an asynchronous call has finished with redux-saga?redux-saga 如何知道异步调用已经完成?
【发布时间】:2019-07-13 14:33:28
【问题描述】:

点击一个按钮,我发送一个动作来发出一个获取请求,我想在继续之前等待请求完成,这样做的正确方法是什么? 我确实根据我的传奇中的结果调度了一个动作:

function* workerSaga() {
try {
  const response = yield call(fetchCall);
  const myData= response.data;

  // dispatch a success action to the store 
  yield put({ type: "API_CALL_SUCCESS", myData});

} catch (error) {
  // dispatch a failure action to the store with the error
  yield put({ type: "API_CALL_FAILURE", error });
}

但是我如何在发送请求操作的代码中知道获取请求已经完成?

提前谢谢。

编辑:

如果没有 saga,请求看起来类似于:

    axios.get(myURL)
    .then(/*here we know the request has finished*/);

与传奇:

this.props.dispatch({type:"API_CALL"})
//here i would like to know the request has finished

【问题讨论】:

  • 您能否详细说明“发送请求操作的代码”?也许您可以在问题正文中提供该代码。了解更多关于您要完成的工作也会有所帮助。
  • 我试图更好地解释我在问什么

标签: reactjs redux generator redux-saga


【解决方案1】:
this.props.dispatch({type:"API_CALL"})
//here i would like to know the request has finished

一般来说,redux saga 不会被组件使用。相反,你的组件应该使用 react-redux 的 connect 方法订阅到 store,所以当 API_CALL_SUCCESS 通过 reducer 并且状态得到更新时,你的组件将获得新的 props 并因此重新渲染。如有必要,您可以实现 componentDidUpdate 以在 prop 更改时运行一些代码。

可以做一个变通的方法,以便您可以通过 promise 了解工作何时完成,但这样做需要在您的组件和您的 saga 之间引入更多的耦合,所以我建议 不要 在大多数情况下使用它。您可以设置您的操作,使其有效负载的一部分是回调函数,然后让 saga 调用该函数。例如:

// In the saga
function* workerSaga(action) {
  try {
    const response = yield call(fetchCall);
    const myData = response.data;

    // dispatch a success action to the store 
    yield put({ type: "API_CALL_SUCCESS", myData});
    if (action.callback) {
      action.callback(myData);
    } 

  } catch (error) {
    // dispatch a failure action to the store with the error
    yield put({ type: "API_CALL_FAILURE", error });
  }
}

// in the component
componentDidMount() {
  this.props.dispatch({ type: 'API_CALL', callback: onFetchSuccess }); 
}

onFetchSuccess(data) {

}

或者如果你想要一个promise,那么回调可以是一个新promise的解析器:

componentDidMount() {
  const promise = new Promise((resolve) => {
    this.props.dispatch({ type: 'API_CALL', callback: resolve }); 
  });
  promise.then(data => {

  });
}

// or, with async/await:
async componentDidMount() {
  const data = await new Promise(resolve => 
    this.props.dispatch({ type: 'API_CALL', callback: resolve })
  );
}

【讨论】:

    【解决方案2】:

    这是一个使用try/catch的示例

    function* workerSaga() {
    
      try {
        const response = yield call(fetchCall);
        if (response.data) { // check based on what the your API returns
          const myData= response.data;
          // dispatch a success action to the store 
          yield put({ type: "API_CALL_SUCCESS", myData});
        } else {
          throw response;
        }
    
      } catch (error) {
        // dispatch a failure action to the store with the error
        yield put({ type: "API_CALL_FAILURE", error });
      }
    }
    

    没有try/catch

    function* workerSaga() {
      const response = yield call(fetchCall);
    
      if (response.data) { // check based on what the your API returns
        const myData= response.data;
    
        // dispatch a success action to the store 
        yield put({ type: "API_CALL_SUCCESS", myData});
      } else {
        // dispatch a failure action to the store with the error
        yield put({ type: "API_CALL_FAILURE", error });
      }
    }
    

    【讨论】: