如何确保一个Saga在另一个之前完成?

时间:2017-08-03 15:54:35

标签: redux redux-saga saga

我是redux-sagas的菜鸟,所以如果我错过了一些明显的东西,请耐心等待我!

我有一个场景,我正在使用redux-saga从OIDC提供程序获取access_token并将其存储在浏览器的localStorage中。 我还使用Sagas从API端点获取一些数据。 但是我一直遇到这种方法的问题,因为在Auth Saga可以使用access_token解析之前调用调用外部API的Saga。

My Auth Saga:

export function * handleFetchTokens () {
  try {
    const token = yield cps(getToken)
    localStorage.setItem('token', token)
    const isAuthenticated = !!(token)
    yield put(actions.checkAuthSuccess(isAuthenticated))
  } catch (e) {
    yield put(actions.checkAuthFailure(e))
  }
}
export default function * sagas () {
  yield fork(takeLatest, actions.CHECK_AUTH, handleFetchTokens)
}

我的API传奇:

export function * handleFetchItems () {
  try {
    const response = yield call(getItems)
    yield put(actions.fetchItemsSuccess(response))
  } catch (e) {
    yield put(actions.fetchItemsFailure(e.errors))
  }
}
export default function * sagas () {
  yield fork(takeLatest, actions.FETCH_ITEMS, handleFetchItems)
}

我的根佐贺:

export default function * root () {
  yield fork(items.sagas)
  yield fork(authentication.sagas)
}

克服这个问题的正确方法应该是什么?

1 个答案:

答案 0 :(得分:0)

就个人而言,我确保在允许我的应用程序的任何部分实际调用FETCH_ITEMS操作之前收到令牌。假设您不想引入此类逻辑,则必须在获取令牌之前决定如何处理FETCH_ITEMS操作。

最简单的方法就是忽略它们,但这也许不是最可行的方法。

剩下的就是缓冲FETCH_ITEMS动作。您可以使用actionChannel执行此操作。由于您使用的是takeLatest,因此您还需要定义大小为1的滑动缓冲区。

它可能看起来像这样:

export default function * sagas () {
  const chan = yield actionChannel(actions.FETCH_ITEMS, buffers.sliding(1))
  yield take('TOKEN_RECEIVED') // wait for action informing us token was received
  chan.close()
  yield fork(takeLatest, chan, handleFetchItems)
  yield fork(takeLatest, actions.FETCH_ITEMS, handleFetchItems)
}

有关actionChannels https://redux-saga.js.org/docs/advanced/Channels.html

的更多信息

另一种方法 - 写入少一点但控制力稍差 - 而不是缓冲就是等待获取传奇本身:

export function * handleFetchItems () {
  while (!token) yield take('TOKEN_RECEIVED');
  ...
}

无论哪种方式,两种方式都依赖于等待收到令牌后需要发送的TOKEN_RECEIVED操作。

相关问题