Rxjs HTTP链式请求错误处理

时间:2018-06-29 20:31:52

标签: reactjs rxjs

在以下代码中,将每个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));
    });
};

1 个答案:

答案 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()
         )
       )
     )
};