我有两个重击,试图将其转换为一个传奇。当用户登录其仪表板时,他们将进行两个API调用,一个用于项目,另一个用于通知。在笨拙中,遵循Flux标准动作调用每个动作的错误是微不足道的,但是我不确定用sagas进行操作的最佳方法是什么。这是我必须开始的:
export function* loadDashboard() {
try {
yield put({ type: types.notificationTypes.GET_NOTIFICATIONS_REQUEST });
const [projects, notifications] = yield all([
DashboardService.getProjects,
DashboardService.getNotifications
]);
yield put({
type: types.projectTypes.GET_PROJECTS_SUCCESS,
payload: projects
});
yield put({
type: types.notificationTypes.GET_NOTIFICATIONS_SUCCESS,
payload: notifications
});
} catch (error) {
//My guess is both of these will render the same error to their reducer,
//regardless of who the originator is
yield put({
type: types.projectTypes.GET_PROJECTS_FAILURE,
error: error.toString()
});
yield put({
type: types.notificationTypes.GET_NOTIFICATIONS_FAILURE,
error: error.toString()
});
}
}
答案 0 :(得分:1)
我认为最好对两个API请求的逻辑进行补偿。
这提高了可读性和可维护性:
export function* loadDashboard() {
yield all([loadProjects, loadNotifications])
}
function* loadProjects() {
try {
yield put({ type: types.GET_PROJECTS_REQUEST })
const projects = yield call(DashboardService.getProjects)
yield put({
type: types.projectTypes.GET_PROJECTS_SUCCESS,
payload: projects
})
} catch (error) {
yield put({
type: types.projectTypes.GET_PROJECTS_FAILURE,
error: error.toString()
})
}
}
function* loadNotifications() {
try {
yield put({ type: types.notificationTypes.GET_NOTIFICATIONS_REQUEST });
const notifications = yield call(DashboardService.getNotifications)
yield put({
type: types.notificationTypes.GET_NOTIFICATIONS_SUCCESS,
payload: notifications
})
} catch (error) {
yield put({
type: types.notificationTypes.GET_NOTIFICATIONS_FAILURE,
error: error.toString()
})
}
}
不过,此代码有些不同。
Redux-saga的all()
is actually all-or-nothing:如果其中一项任务抛出错误,则所有仍在运行的任务都将被取消。
我认为这不是您想要的,因此在我的代码中,我通过捕获每个请求的错误来防止这种情况。
Task cancellation和取消传播是sagas与promise的主要区别。这些东西通常默认情况下会起作用,因此请花一些时间来理解它们。
答案 1 :(得分:0)
我最终将all()
与spawn()
组合在一起:
export function* loadDashboard() {
yield all([
spawn(projectActions.getProjects),
spawn(notificationActions.getNotifications),
spawn(teamActions.getTeams)
]);
}
“分离叉(使用生成) 分离的派生存在于它们自己的执行上下文中。父级不等待分离的分叉终止。产生的任务未捕获的错误不会冒出给父级。并且取消父项不会自动取消分离的分叉(您需要明确地取消它们)。
简而言之,分离的分叉的行为就像root Sagas一样,直接使用middleware.run API开始。”
我通过从3个总数中的一个GET
请求中排除了auth标头来进行了手动测试,并且该错误单独传播,而其他错误继续成功。我运行测试以确保在失败后成功到达了SUCCESS调用。但是,使用3个loadDashboard()
而不是3个fork()
调用编写相同的spawn()
方法时,该行为在功能上似乎是等效的。将需要编写适当的测试来确定哪种方案是此方案的理想选择。