reactjs - Rxjs http 链式请求错误处理
问题描述
在以下代码中,将每个 switchMap 视为步骤。
第 1 步:创建用户(如果尚不可用)
第 2 步:创建对话
第 3 步:返回响应或错误
我们可能会在第 1 步或第 2 步中遇到业务方面的异常,并希望优雅地处理它。我们有更好的处理方法吗?例如,如果我们在步骤 1 中遇到错误,请跳过步骤 2。我们尝试了很多但无法获得更好的解决方案。如果我们只是在步骤 1 中抛出错误
Observable.throw(error)
正在发生自动退订。
const createNewConversationEpic: Epic<Action<{}>, RootState> = (
action$: ActionsObservable<Action<Conversation | User | Error>>
) => {
return action$
.ofType(ConversationsActions.CREATE_NEW_CONVERSATION).pipe(
switchMap((action: Action<User>) => {
return action.payload.id
? Observable.of(action.payload)
: createNewLead(action.payload).pipe(
map(data => data),
catchError(error => {
return Observable.of(error);
})
);
}),
switchMap((response) => {
if (!(response instanceof Error)) {
return createNewConversation({ userId: response.id.toString() }).pipe(
map(data => ConversationsActions.CreateNewConversationSuccess(data)),
catchError(error => {
return Observable.of(error);
})
);
} else {
return Observable.of(response);
}
}),
switchMap(response => {
if (response instanceof Error) {
return ActionsObservable.of(
ConversationsActions.CreateNewConversationError(response),
ConversationsActions.MessagingGlobalError(response),
ConversationsActions.ResetMessagingGlobalError()
);
} else {
return Observable.of(response);
}
})
);
};
export const createNewLead = (body: {}) => {
return request('/api/v1/lead/create/mobile', AjaxMethod.POST, body);
};
const request = (path: string, method: AjaxMethod, body: {}) => {
const url = path;
return ajax({
body,
headers: {
Authorization: 'Bearer ' + getAuthToken(),
'Content-Type': 'application/json'
},
method,
responseType: 'json',
timeout: 120000, // 2 min
url
})
.map(e => {
console.log('[AJAX] Status --- ' + e.status);
console.log(e.response);
return e.response;
})
.catch(err => {
console.log(err);
let error = 'Error while executing request';
if (err.status === 400 || err.status === 412) {
if (err.response.error) {
error = err.response.error;
} else {
error = err.response.message;
}
}
// Handle 401 Status
if (err.status === 401) {
clearLocalstorage();
window.location.href =
window.location.origin +
'/authentication/?src=' +
window.location.pathname;
}
if (err.status === 403) {
error = 'Oops! Looks like you don\'t have access to it';
}
return Observable.throw(new Error(error));
});
};
解决方案
如果您需要停止自动取消订阅,您只需将您期望有错误的管道包装在另一个可以处理异常的流中,就像您使用标准的 try/catch 一样,只要您捕获错误并且在返回外部流之前处理它,父订阅保持不变。
const createNewConversationEpic: Epic<Action<{}>, RootState> = (
action$: ActionsObservable<Action<Conversation | User | Error>>
) => {
return action$
.ofType(ConversationsActions.CREATE_NEW_CONVERSATION).pipe(
// Parent Stream
switchMap((action: Action<User>) =>
// Start child stream
iif(() => action.payload.id,
Observable.of(action.payload),
createNewLead(action.payload)
).pipe(
// Process event as a "happy-path" since errors get forwarded to the end
switchMap((response) => createNewConversation({ userId: response.id.toString() })),
// Move this inline with the rest of the inner pipe line.
map(data => ConversationsActions.CreateNewConversationSuccess(data)),
// Catch all errors from this inner pipeline this will stop them from
// propagating to the outer stream.
catchError(e => ActionsObservable.of(
ConversationsActions.CreateNewConversationError(e),
ConversationsActions.MessagingGlobalError(e),
ConversationsActions.ResetMessagingGlobalError()
)
)
)
};
推荐阅读
- unity3d - Unity Terrein Tree Painter 在关卡下绘制
- java - 我需要在 Java 中获取二维数组对象的索引
- java - 通过 CMD 与 Powershell 执行 Java 命令时的差异 - 由句点(“。”)引起
- angular - SyntaxError:JSON中的意外标记o在角度位置1
- powershell - 如何在导出到 CSV 文件时重命名属性?
- javascript - 有没有办法使用以前的 Chrome 版本?
- python-3.x - 使用列表更新字典时出现 ValueError
- c# - 使用 HttpContext cookie 有没有办法允许在浏览器关闭时删除它以及有一个到期时间?
- android - 如何在 AOSP 源代码中添加预构建的应用程序(系统应用程序)
- php - 跨所有相关数组键同步数组值