У вас є кілька варіантів, залежно від ваших потреб. Якщо ви хочете обробляти помилки на основі запиту, додайте catch
до свого запиту. Якщо ви хочете додати глобальне рішення, використовуйте HttpInterceptor
.
Відкрийте тут робочий демонстраційний планкер для рішень нижче.
тл; д-р
У найпростішому випадку вам просто потрібно буде додати .catch()
або .subscribe()
, наприклад:
import 'rxjs/add/operator/catch'; // don't forget this, or you'll get a runtime error
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});
// or
this.httpClient
.get("data-url")
.subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
Але тут є детальніше, дивіться нижче.
Метод (локальне) рішення: помилка журналу та відповідь на повернення
Якщо вам потрібно обробляти помилки лише в одному місці, ви можете використовувати catch
і повернути значення за замовчуванням (або порожню відповідь), а не повністю відмовитись. Вам також не потрібно .map
просто грати, ви можете використовувати загальну функцію. Джерело: Angular.io - Отримання відомостей про помилки .
Отже, загальний .get()
метод виглядає так:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class DataService {
baseUrl = 'http://localhost';
constructor(private httpClient: HttpClient) { }
// notice the <T>, making the method generic
get<T>(url, params): Observable<T> {
return this.httpClient
.get<T>(this.baseUrl + url, {params})
.retry(3) // optionally add the retry
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.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 ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value
// return Observable.of<any>({my: "default value..."});
// or simply an empty observable
return Observable.empty<T>();
});
}
}
Поводження з помилкою дозволить вашій програмі продовжувати роботу, навіть коли служба за адресою знаходиться в поганому стані.
Це рішення на запит добре, головним чином, коли ви хочете повернути конкретну відповідь за замовчуванням для кожного методу. Але якщо ви дбаєте лише про відображення помилок (або маєте глобальну відповідь за замовчуванням), кращим рішенням буде використання перехоплювача, як описано нижче.
Тут запустіть робочий демонстраційний плункер .
Розширене використання: перехоплення всіх запитів чи відповідей
Ще раз, посібник Angular.io показує:
Головною особливістю @angular/common/http
перехоплення є можливість оголошення перехоплювачів, які знаходяться між вашою програмою та заднім числом. Коли ваша програма надсилає запит, перехоплювачі трансформують її перед відправкою на сервер, а перехоплювачі можуть перетворити відповідь на зворотному шляху до того, як ваша програма побачить її. Це корисно для всього, починаючи від аутентифікації до реєстрації.
Що, звичайно, можна використовувати для обробки помилок дуже простим способом ( демонстраційний плункер тут ):
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse,
HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.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 ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value (which has to be a HttpResponse here)
// return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
// or simply an empty observable
return Observable.empty<HttpEvent<any>>();
});
}
}
Забезпечення вашого перехоплювача. Якщо просто оголосити HttpErrorInterceptor
вище, ваш додаток не використовує його. Вам потрібно підключити його у своєму модулі програми , надавши його як перехоплювач таким чином:
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpErrorInterceptor } from './path/http-error.interceptor';
@NgModule({
...
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true,
}],
...
})
export class AppModule {}
Примітка: Якщо у вас є як перехоплювач помилок, так і деякі локальні поводження з помилками, природно, ймовірно, що локальне поводження з помилками ніколи не буде спрацьовано, оскільки помилка завжди буде оброблятися перехоплювачем до того, як воно дістанеться до локальної обробки помилок.
Тут запустіть робочий демонстраційний плункер .
return this.httpClient.get<type>(...)
. а потімcatch...
десь поза службою, де він насправді споживає її, тому що там він буде будувати спостережний потік і може впоратися з цим найкраще.