Angular HttpClient: как получить необработанный HTTP-ответ, даже если ошибка - PullRequest
1 голос
/ 03 октября 2019

В службе Angular, использующей HttpClient, я создал метод, который возвращает необработанный HTTP-ответ от POST:

httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
    //observe: 'response'
  }),
  observe: 'response' as 'body'
};

forgotLogin(requestData: PUMRequestData): Observable<HttpResponse<string>> {
  return this.http.post<HttpResponse<string>>("http://...", requestData, this.httpOptions);

Затем в своем компоненте я просто смотрю на статуси тело из необработанного HTTP-ответа.

this.api.forgotLogin(pumRequestData).subscribe(response => {
  this.hStatus = response.status;
  this.hBody = response.body;
});

Проблема в том, что если статус ответа не входит в серию 200, то HttpClient выдает ошибку. В моем случае я просто хочу получить статус и тело запроса независимо от его статуса, и я хочу решить, какое действие предпринять, основываясь на состоянии в моем компоненте, а не в обработчике ошибок в службе. Я пытался придумать какой-нибудь хитрый способ создания обработчика ошибок в службе, который просто возвращает (Наблюдаемый) ответ HTTP, и не смог - даже не уверен, что это правильный подход.

Так как же я могу получить необработанный HTTP-ответ обратно на мой компонент, когда статус не соответствует серии 200?

Ответы [ 2 ]

0 голосов
/ 09 октября 2019

Ну, я сдался и решил с помощью обработчика ошибок, как было предложено (спасибо Кристофер). Мне нужен был http-клиент, который просто передавал бы мне ответ http независимо от статуса и выдавал ошибку только в том случае, если ответ не возвращался (например, несуществующий домен). Angular HttpClient не будет этого делать. Там может быть другая клиентская библиотека http, которая будет, но жизнь слишком коротка.

Мне нужен только статус HTTP и тело из ответа, поэтому я создал этот обработчик ошибок:

  private handleError(error: HttpErrorResponse) {
    if (error.status == 0)
      return of({ status: 600, body: "Unexpected error. If this problem persists, please contact ..." })
    else
      return of({ status: error.status, body: error.error });
  }

Тогда мои методы вызова API выглядят следующим образом:

  changePassword(requestData: PUMRequestData): Observable<HttpResponse<string>> {
    return this.http.put<any>("http:// ... /API/ChangePassword", requestData, this.httpOptions)
      .pipe(catchError(err => this.handleError(err)));
  }

Теперь, независимо от того, получает ли подписчик ответ либо от успешного вызова HTTP Status 200, либо от обработчика ошибок, он будет содержать как «status», так и «body». ». Обратите внимание, что если нет ответа HTTP, тогда я устанавливаю фиктивный HTTP Status 600, и в этом случае я должен предоставить недостающее сообщение об ошибке, которое было бы в теле. Также мне пришлось поменять тип данных пут из строки HttpResponse на любой.

0 голосов
/ 03 октября 2019

Когда вы подписываетесь на ответ HTTP, вы можете добавить обработчик ошибок. Объект HttpErrorResponse включает в себя HttpHeaders, status и statusText, которые наследуются от HttpResponseBase.

body доступно в собственности HttpErrorResponse.error.

HttpResponseBase Свойства доступны на HttpErrorResponse

  • заголовках: HttpHeaders - Все заголовки ответа.
  • status : number - Код состояния ответа.
  • statusText : string - Текстовое описание ответакод состояния. (Не зависит от этого)
  • url : string |null - URL-адрес полученного ресурса или null, если он недоступен.
  • ok : логический - находится ли код состояния в диапазоне 2xx.

Пример

this.api.forgotLogin(pumRequestData).subscribe(
  response => {
    this.hStatus = response.status;
    this.hBody = response.body;
  },
  (error: HttpErrorResponse) => {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(`Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
  }
);

Обработчик ошибок также может быть помещен в RXJS pipe, так что его можно встроить до подписки на HTTPrequest.

this.http.get<Object>(full_url, options).pipe(catchError((error: HttpErrorResponse) => {
  // Process error here, such as logging.
  ...
  return throwError(error)
}))

См. Angular HttpClient документы: Обработка ошибок

...