首页 > 解决方案 > 使用 redux saga 阻止 takeEvery

问题描述

我有两组操作,我希望能够通过 redux 从我的应用程序的不同部分调用它们。但是,我想以正确的顺序运行它们,并确保 set b 永远不会在 set a 之前运行。

例如,假设我有两个动作,configure并且execute. 我需要确保它execute之前从未运行过configure,但它们可能会乱序发送。在这种情况下,我需要execute排队并且只处理一次configure完成。

这可以在 redux-saga 中做到吗?

我尝试了以下方法,似乎根本没有阻塞:

function* configureSaga({ payload }): IterableIterator<any> {
  yield put(aFirstThing(payload));
  yield put(aSecondThing());
}

function* executeSaga({ payload }): IterableIterator<any> {
  yield put(aThirdThing(payload));
  yield put(aFourthThing());
}

export function* adsSaga(): IterableIterator<any> {
  const configureChanel = yield actionChannel({ type: 'configure' });
  yield takeEvery(configureChanel, configureSaga);
  yield takeEvery({ type: 'execute' }), executeSaga);
}

按以下顺序给定两个分派:

dispatch({ type: 'execute' })
dispatch({ type: 'configure' })

我需要按aFirstThing, aSecondThing, aThirdThing, aFourthThing该顺序执行的操作。

redux-sagas 有可能做到这一点吗?

标签: reactjsreduxreact-reduxredux-saga

解决方案


takeEvery对于最常见的情况很有用,但对于更复杂的情况,您通常最终会改为编写自定义循环。实现将根据您希望如何处理配置/执行期间调度的额外操作而有所不同。

忽略所有其他配置/执行操作(在等待第二个操作时)+ 忽略所有操作,直到配置完成:

export function* adsSaga() {
  while (true) {
    const [executePayload, configurePayload] = yield all([
      take('configure'),
      take('execute'),
    ])
    yield call(configureSaga, configurePayload);
    yield fork(executeSaga, executePayload);
  }
}

忽略所有其他配置/执行操作(在等待第二个操作时)+ 缓冲所有操作,直到配置完成:

export function* rootSaga() {
  const configureChan = yield actionChannel('configure');
  const executeChan = yield actionChannel('execute');
  while (true) {
    const [executePayload, configurePayload] = yield all([
      take(configureChan),
      take(executeChan),
    ])
    yield call(configureSaga, configurePayload);
    yield fork(executeSaga, executePayload);
  }
}

要使配置+执行操作等待每个其他人,您可以使用 all+take 的组合。只有当您想处理配置+执行组合的多“轮”时才需要 actionChannel。

您可以修改这些解决方案,例如仅缓冲配置或执行操作。或者,如果您想在配置和执行都完成之前忽略所有操作,请使用call而不是fork运行executeSaga. 您还可以通过将call+fork效果放在另一个分叉 saga 中来允许多个配置同时运行。如果您想一次最多缓冲一个动作,还可以选择将自定义缓冲区传递给动作通道。


推荐阅读