首页 > 解决方案 > 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));
    });
};

标签: reactjsrxjs

解决方案


如果您需要停止自动取消订阅,您只需将您期望有错误的管道包装在另一个可以处理异常的流中,就像您使用标准的 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()
         )
       )
     )
};

推荐阅读