在以下代码中,将每个switchMap视为步骤。
第1步:创建尚不可用的用户
第2步:创建对话
第3步:返回响应或错误
我们可能在第1步或第2步中遇到业务方面的异常,并且希望能够优雅地处理它。我们是否有更好的方法来处理此问题?例如如果我们在步骤1中遇到错误,请跳过步骤2。如果我们只是在步骤1中抛出错误
Observable.throw(错误)
正在自动取消订阅。
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));
});
};
答案 0 :(得分:0)
如果您需要停止自动退订,则只需将希望发生错误的管道包装在可以处理异常的另一个流中,就像捕获/捕获标准捕获/捕获一样错误并在返回父订阅的外部流之前对其进行处理。
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()
)
)
)
};