In meinem Angular 2-Projekt mache ich API-Aufrufe von Diensten, die eine Observable zurückgeben. Der aufrufende Code abonniert dann dieses Observable. Beispielsweise:
getCampaigns(): Observable<Campaign[]> {
return this.http.get('/campaigns').map(res => res.json());
}
Angenommen, der Server gibt eine 401 zurück. Wie kann ich diesen Fehler global abfangen und zu einer Anmeldeseite / Komponente umleiten?
Vielen Dank.
Folgendes habe ich bisher:
// boot.ts
import {Http, XHRBackend, RequestOptions} from 'angular2/http';
import {CustomHttp} from './customhttp';
bootstrap(AppComponent, [HTTP_PROVIDERS, ROUTER_PROVIDERS,
new Provider(Http, {
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
deps: [XHRBackend, RequestOptions]
})
]);
// customhttp.ts
import {Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class CustomHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
console.log('request...');
return super.request(url, options);
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
console.log('get...');
return super.get(url, options);
}
}
Die Fehlermeldung lautet "backend.createConnection ist keine Funktion".
Antworten:
Beschreibung
Die beste Lösung , die ich gefunden habe , ist das außer Kraft zu setzen ,
XHRBackend
so dass der HTTP - Antwort - Status401
und403
führt zu einer bestimmten Aktion.Wenn Sie Ihre Authentifizierung außerhalb Ihrer Angular-Anwendung durchführen, können Sie eine Aktualisierung der aktuellen Seite erzwingen, sodass Ihr externer Mechanismus ausgelöst wird. Ich beschreibe diese Lösung in der folgenden Implementierung.
Sie können auch an eine Komponente in Ihrer Anwendung weiterleiten, sodass Ihre Angular-Anwendung nicht neu geladen wird.
Implementierung
Winkel> 2.3.0
Dank @mrgoos ist hier eine vereinfachte Lösung für Angular 2.3.0+ aufgrund einer Fehlerbehebung in Angular 2.3.0 (siehe Problem https://github.com/angular/angular/issues/11606 ), die das
Http
Modul direkt erweitert .Die Moduldatei enthält nur noch den folgenden Anbieter.
Eine weitere Lösung, die einen Router und einen externen Authentifizierungsdienst verwendet, wird in der folgenden Übersicht von @mrgoos beschrieben.
Winkel vor 2.3.0
Die folgende Implementierung funktioniert für
Angular 2.2.x FINAL
undRxJS 5.0.0-beta.12
.Es wird zur aktuellen Seite umgeleitet (plus einem Parameter, um eine eindeutige URL zu erhalten und das Caching zu vermeiden), wenn ein HTTP-Code 401 oder 403 zurückgegeben wird.
mit der folgenden Moduldatei.
quelle
catch()
nicht gefunden wurde. (smh)import "rxjs/add/operator/catch";
http
? Der einzige Vorteil, den ich sehe, ist, dass Sie es einfach als Anbieter angeben können:{ provide: XHRBackend, useClass: AuthenticationConnectionBackend }
Wenn Sie HTTP überschreiben, müssen Sie umständlicheren Code schreibenuseFactory
und sich einschränken, indem Sie "neu" aufrufen und bestimmte Argumente senden. WDYT? Ein Verweis auf die 2. Methode: adonespitogo.com/articles/angular-2-extending-http-providerWinkel 4.3+
Mit der Einführung von HttpClient wurde die Möglichkeit geschaffen, alle Anfragen / Antworten einfach abzufangen. Die allgemeine Verwendung von HttpInterceptors ist gut dokumentiert. Informationen zur grundlegenden Verwendung und zur Bereitstellung des Interceptors finden Sie hier. Unten finden Sie ein Beispiel für einen HttpInterceptor, der 401-Fehler verarbeiten kann.
Aktualisiert für RxJS 6+
RxJS <6
quelle
Router
hier zu verwenden scheint nicht zu funktionieren. Zum Beispiel möchte ich meine Benutzer zur Anmeldeseite weiterleiten, wenn sie einen 401-403 erhalten,this.router.navigate(['/login']
funktioniert aber nicht für mich. Es macht nichtsimport 'rxjs/add/operator/do';
Sie nach dem Importieren von rxjs hinzu.Da Frontend-APIs mit Angular 6+ und RxJS 5.5+ schneller ablaufen als Milch, müssen Sie Folgendes verwenden
pipe
:Update für Angular 7+ und rxjs 6+
quelle
error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable<HttpEvent<any>>'.
wenn das.pipe
.pipe
req
ist tatsächlichrequest
- die Bearbeitung ist zu klein für michDie, die
Observable
Sie von jeder Anforderungsmethode erhalten, ist vom TypObservable<Response>
. DasResponse
Objekt hat einestatus
Eigenschaft, die das enthält401
IF enthält, wenn der Server diesen Code zurückgegeben hat. Vielleicht möchten Sie das abrufen, bevor Sie es zuordnen oder konvertieren.Wenn Sie diese Funktionalität bei jedem Aufruf vermeiden möchten, müssen Sie möglicherweise die
Http
Klasse von Angular 2 erweitern und eine eigene Implementierung einfügen, die parent (super
) für die reguläreHttp
Funktionalität aufruft, und dann den401
Fehler behandeln, bevor Sie das Objekt zurückgeben.Sehen:
https://angular.io/docs/ts/latest/api/http/index/Response-class.html
quelle
Winkel 4.3+
Um den Gilbert Arenas Dolch zu vervollständigen Antwort von :
Wenn Sie einen Fehler abfangen müssen, eine Behandlung darauf anwenden und ihn entlang der Kette weiterleiten (und nicht nur einen Nebeneffekt hinzufügen
.do
), können Sie HttpClient und seine Abfangjäger verwenden, um etwas in der Art zu tun:quelle
Um das Problem der zyklischen Referenzierung zu vermeiden, das durch das Injizieren von Diensten wie "Router" in eine von HTTP abgeleitete Klasse verursacht wird, muss die Post-Konstruktor-Injector-Methode verwendet werden. Der folgende Code ist eine funktionierende Implementierung eines HTTP-Dienstes, der jedes Mal, wenn eine REST-API "Token_Expired" zurückgibt, zur Anmelderoute umleitet. Beachten Sie, dass es als Ersatz für das reguläre HTTP verwendet werden kann und daher keine Änderungen an den bereits vorhandenen Komponenten oder Diensten Ihrer Anwendung erforderlich macht.
app.module.ts
erweitert-http.service.ts
quelle
Ab Angular> = 2.3.0 können Sie das
HTTP
Modul überschreiben und Ihre Dienste einspeisen. Vor Version 2.3.0 konnten Sie Ihre injizierten Dienste aufgrund eines Kernfehlers nicht verwenden.Ich habe einen Kern erstellt, um zu zeigen, wie es gemacht wird.
quelle
app.module
Code teilen ? Vielen Dank.HTTP
woanders?Winkel> 4.3: ErrorHandler für den Basisdienst
quelle