如何等待传奇的执行在redux-saga中完成?

时间:2018-10-12 21:38:57

标签: reactjs redux react-redux redux-saga

我有以下情况:

export function* addCircle(circleApi, { payload }) {
    try {
        const response = yield apply(
            circleApi,
            circleApi.addCircle,
            [payload]
        );

        if (response.error_type) {
           yield put(addCircleFailedAction(response.error));
        } else {
            yield put(addCircleSucceededAction(response));
        }
    } catch (err) {
        console.error(err);
    }
}

export function* addTender(tenderApi, { payload }) {
    try {
       // NOTE: I want this to finish before continuing with rest of saga below.
       yield call(addCircleAction(payload.circlePayload));

       // Rest of saga removed for brevity.
    } catch (err) {
        console.error(err);
    }
}

因此,基本上addCircle正在进行API调用,并根据其成功调用适当的redux操作。现在,在另一个传奇中,我将负责addCircle传奇的动作称为“动作”,并且我希望它在继续其余传奇之前完成执行。我尝试使用call,但是它基本上不等待addCircle传奇完成执行。有什么方法可以等待吗?我从组件内部调用addCircle,而无需等待,但是在这种特定情况下,我必须在saga中调用它,因此我真的需要等待它完成执行,更改应用程序的状态,以便我可以在其余addTender传奇中使用更新后的状态。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

根据您的代码片段,您的addCircle传奇故事将在执行完成之前分派addCircleFailedActionaddCircleSucceededAction动作创建者。因此,我们将不得不等待您的addTender传奇故事中的那些动作。

基本上,这是您应该做的。我只是根据动作创建者的名字猜测您的动作类型。

yield call(addCircleAction(payload.circlePayload));
yield take([ADD_CIRCLE_FAILED_ACTION, ADD_CIRCLE_SUCCEEDED_ACTION]);

// Rest of the saga

虽然有一个极端的情况。您没有在catch故事的addCircle块中调度任何操作。也许您可以在addCircleExceptionAction块内分派一个名为catch的动作,并与其他其他动作一起等待,例如:

yield take([ADD_CIRCLE_FAILED_ACTION, ADD_CIRCLE_SUCCEEDED_ACTION, ADD_CIRCLE_EXCEPTION_ACTION]);

答案 1 :(得分:0)

如果您要调度多个将触发addRender的动作,则无法保证take(...)实际上会等待yield调用所导致的动作。

export function* addCircle(circleApi, { payload }) {
  try {
      const response = yield apply(
          circleApi,
          circleApi.addCircle,
          [payload]
      );

      if (response.error_type) {
         yield put(addCircleFailedAction(response.error));
         return response;
      } else {
          yield put(addCircleSucceededAction(response));
          return response;
      }
  } catch (err) {
      console.error(err);
      return {err};
  }
}

export function* addTender(tenderApi, { payload }) {
  try {
     //because addCircle saga is returning something you can re use it
     // in other sagas.
     const result = yield call(addCircle,circleAPI?,payload.circlePayload);
     //check for result.error_type here
     // Rest of saga removed for brevity.
  } catch (err) {
      console.error(err);
  }
}

您的代码和可接受的答案将导致错误,因为call不会将操作对象作为第一个参数(它确实会接受{context,fn}类型的对象)。

分派一个动作,然后再听另一个或可能不是您刚分派的动作的副作用的动作,是不好的设计。您以异步方式分派这些操作,并且不能保证它们全部花费相同的时间来完成或以开始时的顺序提供您正在等待的副作用。