Rxjs http цепочка обработки ошибок запроса - PullRequest
0 голосов
/ 29 июня 2018

В следующем коде рассмотрите каждую карту switchMap как шаг.

Шаг 1. Создайте пользователя, если он еще не доступен

Шаг 2: Создать разговор

Шаг 3. Обратный ответ или ошибка

Мы могли бы получить исключение со стороны бизнеса на шаге 1 или шаге 2 и хотели бы обработать это элегантно. У нас есть лучший способ справиться с этим? например Просто пропустите шаг 2, если мы получили ошибку на шаге 1. Мы много пытались, но не смогли найти лучшее решение. Если мы просто выбросим ошибку в шаге 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 голосов
/ 01 июля 2018

Если вам нужно остановить автоматическую отмену подписки, вам просто нужно обернуть конвейер, который, как вы ожидаете, будет иметь ошибку в другом потоке, который может обработать исключение, точно так же, как вы делаете стандартную попытку / перехват, пока вы захватываете ошибка и обработайте ее перед возвратом во внешний поток родительской подписки без изменений.

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()
         )
       )
     )
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...