我是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)
}
克服这个问题的正确方法应该是什么?
答案 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操作。