如何根据 API accessToken 构建传奇
How to structure sagas depending on an API accessToken
我有一个 saga loginSaga
,它执行 api 调用以获得 accessToken
。
一旦成功,我想有一堆其他的传奇来用这个 accessToken
来加速下载数据
那些传说依赖于 accessToken
,所以它们应该只 运行 直到 LOGOUT_SUCCESS
出现。然后他们应该完成。如果他们当前正在下载某些内容,则应取消此操作,结果将被忽略。
这是我现在拥有的:
function *authorize(credentials) {
try {
const { email, password, device_name, device_family, device_token } = credentials
const { access_token, user } = yield call(api.loginAsync, email, password, { device_name, device_family, device_token })
yield put(actions.loginSuccess(access_token, user))
} catch(error) {
console.error(error)
if (!isCancelError(error)) {
if (error.response && error.response.status == 401) {
error.message = "E-Mail or Password wrong"
}
yield put(actions.loginError(error))
}
}
}
function *loginFlow() {
while(true) {
console.info("Waiting for account/LOGIN")
const credentials = yield take(actions.LOGIN)
const authorizeTask = yield fork(authorize, credentials)
console.info("Waiting for account/LOGOUT")
const { type } = yield take([actions.LOGOUT, actions.LOGIN_ERROR])
cancel(authorizeTask)
if (type == actions.LOGOUT) {
yield call(api.logoutAsync)
yield put(actions.logoutSuccess())
}
}
}
然后 LOGIN_SUCESS
取决于传奇:
function *refreshUser() {
while (true) {
const result = yield take([actions.LOGIN_SUCCESS, actions.REFRESH_USER])
try {
const user = yield call(api.getUserAsync)
yield put(actions.userRefreshed(user))
} catch (error) {
}
}
}
function *getActivities(access_token) {
console.info("fetch activities")
try {
const activities = yield call(api.getActivitiesAsync, access_token)
console.info("activities fetched")
yield put(activitiesUpdated(activities))
} catch (error) {
}
}
function *updateActivities() {
while (true) {
const { access_token } = yield take(actions.LOGIN_SUCCESS)
console.info("Calling getActivities")
yield call(getActivities, access_token)
while (true) {
const {type } = yield take([actions.REFRESH_ACTIVITIES, actions.LOGOUT])
if (type == actions.LOGOUT) {
break
}
yield call(getActivities, access_token)
}
}
}
并且由于他们都需要 accessToken
,所以他们都必须等到 LOGIN_FINISHED
,因为这会在有效载荷中携带它。
还有我的sagas都是从头开始等等
我想也许,当 authorize
流程完成时,它可以将 loginDependingSagas
与 accessToken
作为参数一起旋转。
像这样:
function forkLoginDependingSagas(accessToken) {
分叉刷新用户(accessToken)
分叉更新活动(accessToken)
}
这样的模式好吗?
我使用一个单独的 saga 解决了这个问题,它等待携带 access_token
的动作,然后根据这个 access_token
.
派生 sagas
function* authorizedFlow() {
let payload
while (({ payload } = yield take([actions.LOGIN_SUCCESS, actions.START_SIGNUP_SUCCESS]))) {
const { access_token } = payload
yield fork(logoutFlow, access_token)
yield race({
watchers: [
call(refreshUser, access_token),
call(refreshInvoices, access_token),
call(refreshPendingTransactions, access_token),
],
logout: take(actions.LOGOUT_SUCCESS),
})
}
}
function* logoutFlow(access_token) {
while (yield take(actions.LOGOUT)) {
try {
yield call(api.logoutAsync, access_token)
yield put(actions.logoutSuccess())
} catch (error) {
yield put(actions.logoutError(error))
}
}
}
logoutFlow 将确保 access_token
依赖的 sagas 之间的 race
在注销成功的情况下取消它们。
我有一个 saga loginSaga
,它执行 api 调用以获得 accessToken
。
一旦成功,我想有一堆其他的传奇来用这个 accessToken
那些传说依赖于 accessToken
,所以它们应该只 运行 直到 LOGOUT_SUCCESS
出现。然后他们应该完成。如果他们当前正在下载某些内容,则应取消此操作,结果将被忽略。
这是我现在拥有的:
function *authorize(credentials) {
try {
const { email, password, device_name, device_family, device_token } = credentials
const { access_token, user } = yield call(api.loginAsync, email, password, { device_name, device_family, device_token })
yield put(actions.loginSuccess(access_token, user))
} catch(error) {
console.error(error)
if (!isCancelError(error)) {
if (error.response && error.response.status == 401) {
error.message = "E-Mail or Password wrong"
}
yield put(actions.loginError(error))
}
}
}
function *loginFlow() {
while(true) {
console.info("Waiting for account/LOGIN")
const credentials = yield take(actions.LOGIN)
const authorizeTask = yield fork(authorize, credentials)
console.info("Waiting for account/LOGOUT")
const { type } = yield take([actions.LOGOUT, actions.LOGIN_ERROR])
cancel(authorizeTask)
if (type == actions.LOGOUT) {
yield call(api.logoutAsync)
yield put(actions.logoutSuccess())
}
}
}
然后 LOGIN_SUCESS
取决于传奇:
function *refreshUser() {
while (true) {
const result = yield take([actions.LOGIN_SUCCESS, actions.REFRESH_USER])
try {
const user = yield call(api.getUserAsync)
yield put(actions.userRefreshed(user))
} catch (error) {
}
}
}
function *getActivities(access_token) {
console.info("fetch activities")
try {
const activities = yield call(api.getActivitiesAsync, access_token)
console.info("activities fetched")
yield put(activitiesUpdated(activities))
} catch (error) {
}
}
function *updateActivities() {
while (true) {
const { access_token } = yield take(actions.LOGIN_SUCCESS)
console.info("Calling getActivities")
yield call(getActivities, access_token)
while (true) {
const {type } = yield take([actions.REFRESH_ACTIVITIES, actions.LOGOUT])
if (type == actions.LOGOUT) {
break
}
yield call(getActivities, access_token)
}
}
}
并且由于他们都需要 accessToken
,所以他们都必须等到 LOGIN_FINISHED
,因为这会在有效载荷中携带它。
还有我的sagas都是从头开始等等
我想也许,当 authorize
流程完成时,它可以将 loginDependingSagas
与 accessToken
作为参数一起旋转。
像这样:
function forkLoginDependingSagas(accessToken) { 分叉刷新用户(accessToken) 分叉更新活动(accessToken) }
这样的模式好吗?
我使用一个单独的 saga 解决了这个问题,它等待携带 access_token
的动作,然后根据这个 access_token
.
function* authorizedFlow() {
let payload
while (({ payload } = yield take([actions.LOGIN_SUCCESS, actions.START_SIGNUP_SUCCESS]))) {
const { access_token } = payload
yield fork(logoutFlow, access_token)
yield race({
watchers: [
call(refreshUser, access_token),
call(refreshInvoices, access_token),
call(refreshPendingTransactions, access_token),
],
logout: take(actions.LOGOUT_SUCCESS),
})
}
}
function* logoutFlow(access_token) {
while (yield take(actions.LOGOUT)) {
try {
yield call(api.logoutAsync, access_token)
yield put(actions.logoutSuccess())
} catch (error) {
yield put(actions.logoutError(error))
}
}
}
logoutFlow 将确保 access_token
依赖的 sagas 之间的 race
在注销成功的情况下取消它们。