Sie haben je nach Bedarf einige Optionen. Wenn Sie Fehler pro Anfrage behandeln möchten, fügen Sie catch
Ihrer Anfrage ein hinzu. Wenn Sie eine globale Lösung hinzufügen möchten, verwenden Sie HttpInterceptor
.
Öffnen Sie hier den funktionierenden Demo-Plunker für die folgenden Lösungen.
tl; dr
Im einfachsten Fall müssen Sie nur ein .catch()
oder ein hinzufügen .subscribe()
, wie:
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)
);
Aber es gibt noch mehr Details dazu, siehe unten.
Methode (lokal) Lösung: Fehler protokollieren und Fallback-Antwort zurückgeben
Wenn Sie Fehler nur an einer Stelle behandeln müssen, können Sie catch
einen Standardwert (oder eine leere Antwort) verwenden und zurückgeben, anstatt vollständig fehlzuschlagen. Sie brauchen auch nicht .map
nur das Casting, sondern können eine generische Funktion verwenden. Quelle: Angular.io - Abrufen von Fehlerdetails .
Eine generische .get()
Methode wäre also wie folgt:
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>();
});
}
}
Durch die Behandlung des Fehlers kann die App auch dann fortgesetzt werden, wenn sich der Dienst unter der URL in einem schlechten Zustand befindet.
Diese Lösung pro Anforderung eignet sich vor allem dann, wenn Sie für jede Methode eine bestimmte Standardantwort zurückgeben möchten. Wenn Sie sich jedoch nur für die Fehleranzeige interessieren (oder eine globale Standardantwort haben), ist die bessere Lösung die Verwendung eines Interceptors, wie unten beschrieben.
Führen Sie hier den funktionierenden Demo-Plunker aus .
Erweiterte Verwendung: Abfangen aller Anforderungen oder Antworten
Der Angular.io-Leitfaden zeigt einmal mehr:
Ein Hauptmerkmal von @angular/common/http
ist das Abfangen, die Fähigkeit, Abfangjäger zu deklarieren, die zwischen Ihrer Anwendung und dem Backend liegen. Wenn Ihre Anwendung eine Anforderung stellt, transformieren Interceptors diese, bevor sie an den Server gesendet werden, und die Interceptors können die Antwort auf dem Rückweg transformieren, bevor Ihre Anwendung sie sieht. Dies ist nützlich für alles von der Authentifizierung bis zur Protokollierung.
Was natürlich verwendet werden kann, um Fehler auf sehr einfache Weise zu behandeln ( Demo-Plunker hier ):
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>>();
});
}
}
Bereitstellung Ihres Abfangjägers: Wenn Sie nur das HttpErrorInterceptor
oben Gesagte deklarieren, wird es von Ihrer App nicht verwendet. Sie müssen es in Ihrem App-Modul verkabeln, indem Sie es wie folgt als Interceptor bereitstellen:
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 {}
Hinweis: Wenn Sie sowohl einen Fehlerabfangjäger als auch eine lokale Fehlerbehandlung haben, wird natürlich wahrscheinlich nie eine lokale Fehlerbehandlung ausgelöst, da der Fehler immer vom Abfangjäger behandelt wird, bevor er die lokale Fehlerbehandlung erreicht.
Führen Sie hier den funktionierenden Demo-Plunker aus .
return this.httpClient.get<type>(...)
. und danncatch...
irgendwo außerhalb des Dienstes haben, wo er es tatsächlich konsumiert, weil er dort Observables Flow aufbauen wird und am besten damit umgehen kann.Promise<Object>
Client (den Aufrufer derDataService
Methoden) zu haben, um den Fehler zu behandeln. Beispiel :this.dataService.post('url', {...}).then(...).catch((e) => console.log('handle error here instead', e));
. Wählen Sie aus, was für Sie und die Benutzer Ihres Dienstes klarer ist.return Observable.of({my: "default value..."});
Es wird der Fehler "| ... 'kann nicht dem Typ' HttpEvent <any> 'zugewiesen werden."HttpEvent
, zHttpResponse
. So könnten Sie zum Beispiel verwenden :return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
. Ich habe die Antwort aktualisiert, um diesen Punkt klar zu machen. Außerdem habe ich einen funktionierenden Demo-Plunker erstellt, um zu zeigen, dass alles funktioniert: plnkr.co/edit/ulFGp4VMzrbaDJeGqc6q?p=previewLassen Sie mich das bitte aktualisieren acdcjunior ‚s Antwort über die Verwendung von HttpInterceptor mit den neuesten RxJs Funktionen (V. 6).
quelle
Mit dem Eintreffen der
HTTPClient
API wurde nicht nur dieHttp
API ersetzt, sondern auch eine neue hinzugefügt, dieHttpInterceptor
API.AFAIK hat sich zum Ziel gesetzt, allen ausgehenden HTTP-Anforderungen und eingehenden Antworten ein Standardverhalten hinzuzufügen.
So assumming , dass Sie einen hinzufügen möchten Standardfehlerbehandlung Verhalten , das Hinzufügen ,
.catch()
um alle Ihre möglichen http.get / Post / etc Methoden ist lächerlich schwer zu pflegen.Dies könnte folgendermaßen als Beispiel mit a erfolgen
HttpInterceptor
:// app.module.ts
Einige zusätzliche Informationen für OP: Das Aufrufen von http.get / post / etc ohne einen starken Typ ist keine optimale Verwendung der API. Ihr Service sollte folgendermaßen aussehen:
Die Rückkehr
Promises
von Ihren Servicemethoden anstelle vonObservables
ist eine weitere schlechte Entscheidung.Und noch ein zusätzlicher Ratschlag: Wenn Sie ein TYPE- Skript verwenden, beginnen Sie mit der Verwendung des Typs. Sie verlieren einen der größten Vorteile der Sprache: die Art des Wertes zu kennen, mit dem Sie es zu tun haben.
Wenn Sie meiner Meinung nach ein gutes Beispiel für einen eckigen Service wünschen, schauen Sie sich das folgende Wesentliche an .
quelle
this.http.get()
etc. sein und nichtthis.get()
etc. inDataService
?Bei Angular 6+ funktioniert .catch nicht direkt mit Observable. Du musst benutzen
Unter Code:
Weitere Informationen finden Sie im Angular Guide for Http
quelle
Ziemlich einfach (im Vergleich zu der vorherigen API).
Quelle aus (kopieren und einfügen) dem offiziellen Angular-Leitfaden
quelle
Angular 8 Httpclient Fehlerbehandlung Service - Beispiel
api.service.ts
quelle
Sie möchten wahrscheinlich so etwas haben:
Es hängt auch stark davon ab, wie Sie Ihren Service nutzen, aber dies ist der Grundfall.
quelle
Nach der Antwort von @acdcjunior habe ich es so implementiert
Bedienung:
Anrufer:
quelle
quelle
Wenn Sie feststellen, dass Sie mit keiner der hier bereitgestellten Lösungen Fehler abfangen können, verarbeitet der Server möglicherweise keine CORS-Anforderungen.
In diesem Fall kann Javascript, geschweige denn Angular, auf die Fehlerinformationen zugreifen.
Suchen Sie in Ihrer Konsole nach Warnungen, die
CORB
oder enthaltenCross-Origin Read Blocking
.Außerdem hat sich die Syntax für die Behandlung von Fehlern geändert (wie in jeder anderen Antwort beschrieben). Sie verwenden jetzt Pipe-fähige Operatoren wie folgt:
quelle
Mit Interceptor können Sie Fehler abfangen. Unten ist Code:
Sie können diesen Blog bevorzugen .. gegebenes einfaches Beispiel dafür.
quelle