Angular-Anleitung für Anfänger: HTTP Anfragen
German (Deutsch) translation by Ahmet Öztürk (you can also view the original English article)
Wenn Sie auf der Suche nach Angular-Schulungsmaterial sind, haben Sie Glück. Dieses Lehrmaterial zu Angular auf Deutsch wird Ihnen helfen, in kürzester Zeit loszulegen! Bei Angular HTTP geht es darum, die richtigen Techniken einzusetzen, um eine einseitige Angular HTML Anwendung zu erstellen, die HTTP-Anfragen erstellt und HTTP-Antworten auf einfache und skalierbare Weise verarbeitet. Das Paket @angular/common/http enthält einen Client, einen Interceptor und viele weitere Funktionen für Ihre Angular-Anwendung.
Single Page Applikationen müssen oft skaliert werden, und das Framework muss die richtige Mischung aus Tools und Techniken bieten, um dies zu unterstützen. Angular verfügt über viele eingebaute Tools, um anständig zu skalieren. Heute lernen Sie, wie Sie eine grundlegende Architektur für HTTP-Anfragen in Ihrer Anwendung einrichten und wie Sie Abfangmechanismen verwenden, um Ihre Anwendung skalierbar zu halten.
Groß oder klein, jede Angular-Anwendung wird einen Strom von HTTP-Anfragen haben. Sie werden HTTP-Anfragen senden und empfangen. Wie würden Sie Regeln anwenden und den Ablauf Ihrer Anfragen ändern? Interceptors sind Angular-Dienste, mit denen Sie dies erreichen können. Wie der Name schon sagt, können Sie jede gesendete Anfrage oder empfangene Antwort abfangen. Sie sind in der Lage, die Werte der Anfrage hinzuzufügen oder zu ändern.
Aber bevor Sie sich an HTTP-Abfangmechanismen (Interceptors) wagen, müssen Sie die Grundlagen von HTTP in Angular kennen.
Die Grundstruktur des Projekts
Bevor wir loslegen, möchte ich Ihnen die Gesamtstruktur des Projekts vorstellen. Sie finden das fertige Projekt live in diesem GitHub Repository.
1 |
-src |
2 |
--app |
3 |
----child |
4 |
------child.component.ts |
5 |
----parent |
6 |
------parent.component.ts |
7 |
------parent.service.ts |
8 |
----utility |
9 |
------header.interceptor.ts |
10 |
------response.interceptor.ts |
11 |
------error.interceptor.ts |
12 |
----app-routing.module.ts |
13 |
----app.component.css |
14 |
----app.component.ts |
15 |
----app.module.ts |
16 |
--assets |
1. Ihr Projekt für HTTP vorbereiten
HttpClient ist eine eingebaute Service-Klasse aus dem Angular-Paket: @angular/common/http. Wenn Sie in Angular über ein HTTP-Protokoll kommunizieren wollen, können Sie fetch oder XMLHttpRequest verwenden. In jedem Fall erfolgt die Kommunikation über HttpClient. Diese Serviceklasse verfügt über viele interessante Signaturen und Rückgabetypen.
Interessante Merkmale des HttpClient sind:
- Ausführen von
GET,POST,PUTundDELETEAnfragen - So können Sie alle Ihre Fehlerbehandlungsstrategien optimieren
- Fangen Sie jede gesendete
HTTP-Anfrage oder empfangene Antwort ab - Erstellen Sie typisierte Anfrage- oder Antwortobjekte
- Einführen von
RxJSObservablen
Schritt 1: Importieren von HttpClient in app.module.ts
Um HttpClient verwenden zu können, müssen Sie das HttpClientModule in Ihrer app.module.ts Datei importieren. Und dies sollte Teil des Arrays imports in Ihrem NgModule sein.
1 |
import { NgModule } from '@angular/core'; |
2 |
import { BrowserModule } from '@angular/platform-browser'; |
3 |
import { HttpClientModule } from '@angular/common/http'; |
4 |
|
5 |
@NgModule({ |
6 |
imports: [BrowserModule, HttpClientModule], |
7 |
.
|
8 |
.
|
9 |
providers: [] |
10 |
})
|
11 |
export class AppModule { } |
Mit der obigen Deklaration sind Sie bereit, den HttpClient in Ihren Komponenten zu verwenden. Um auf den HttpClient in einer Komponente zuzugreifen, müssen Sie einen Service erstellen, und zwar einen Injectable Service. Für unseren Zweck werden wir einen Dienst erstellen, der auf Root-Ebene injiziert werden kann.
Schritt 2: Erstellen eines injizierbaren Dienstes
Jeder injizierbare Dienst hat das folgende Grundgerüst. In unserem Beispielprojekt finden Sie einen injizierbaren Service in der Datei parent.service.ts. Er bietet alle APIs, die von parent.component.ts.
1 |
import { HttpClient } from '@angular/common/http'; |
2 |
import { Injectable } from '@angular/core'; |
3 |
|
4 |
@Injectable({ |
5 |
providedIn: 'root' |
6 |
})
|
7 |
|
8 |
export class HttpService { |
9 |
constructor(private https: HttpClient) { } |
10 |
}
|
Nun lassen Sie uns das obige Skelett verbessern und dafür sorgen, dass es Daten von einer API abruft. Wenn Sie neu im Bereich HTTP sind, haben wir einen großartigen Beitrag, der Ihnen hilft, die Grundlagen zu erlernen.
1 |
import { HttpClient, HttpHeaders } from '@angular/common/http'; |
2 |
import { Injectable } from '@angular/core'; |
3 |
import {HttpParams} from "@angular/common/http"; |
4 |
|
5 |
@Injectable({ |
6 |
providedIn: 'root' |
7 |
})
|
8 |
|
9 |
export class ParentHttpService { |
10 |
|
11 |
private url = 'https://reqres.in/api/users'; |
12 |
|
13 |
constructor(private http: HttpClient) { } |
14 |
|
15 |
getUsers() { |
16 |
return this.http.get(this.url); |
17 |
}
|
18 |
|
19 |
// ...
|
20 |
}
|
Schritt 3: Verwendung der Injectable Services
In unserer Datei parent.service.ts finden Sie viele Getter-API-Aufrufe. Diese APIs werden von parent.component.ts aus aufgerufen. Werfen wir einen kurzen Blick auf parent.component.ts, die für den Aufruf der Methoden in parent.service.ts verwendet wird.
Was wir hier erreichen wollen, ist eine Injektion des Dienstes, der zum Abrufen von Benutzern erstellt wurde.
- Wir
abonnierendie Methode des Dienstes. - In dem Moment, in dem wir diese Methode ausführen, werden wir die
GET-Anfrage ausführen und das Antwort-/Fehlerobjekt empfangen.
In unserem Beispiel haben wir drei verschiedene Schaltflächen, die jeweils auf eine andere Methode im injizierbaren Dienst verweisen.
1 |
import { Component } from '@angular/core'; |
2 |
import { ParentHttpService } from './parent.service'; |
3 |
|
4 |
@Component({ |
5 |
selector: 'parent', |
6 |
template: ` |
7 |
<div>
|
8 |
<h3>Parent Page</h3>
|
9 |
<div>Get All Users <button (click)="getAllUsers()">Get All Users</button></div>
|
10 |
<div>Get users in page 2 <button (click)="getUserInPageTwo()">Get Items on Page 2</button></div>
|
11 |
<div>Get users in page 2 with custom Header <button (click)="getUsersOnAPageWithHeaders()">Get users in page 2 with custom Header</button></div>
|
12 |
<div>Users:</div>
|
13 |
<div>{{users}}</div>
|
14 |
</div>
|
15 |
`, |
16 |
})
|
17 |
export class ParentComponent { |
18 |
|
19 |
users : any; |
20 |
|
21 |
constructor(private httpService: ParentHttpService) { } |
22 |
|
23 |
ngOnInit() {} |
24 |
|
25 |
getAllUsers = () => { |
26 |
this.httpService.getUsers().subscribe( |
27 |
(response) => { this.users = JSON.stringify(response); }, |
28 |
(error) => { console.log(error); }); |
29 |
}
|
30 |
getUserInPageTwo = () => { |
31 |
this.httpService.getUsersOnAPage(2).subscribe( |
32 |
(response) => { this.users = JSON.stringify(response); }, |
33 |
(error) => { console.log(error); }); |
34 |
}
|
35 |
getUsersOnAPageWithHeaders = () => { |
36 |
this.httpService.getUsersOnAPageWithHeaders(2).subscribe( |
37 |
(response) => { this.users = JSON.stringify(response); }, |
38 |
(error) => { console.log(error); }); |
39 |
}
|
40 |
|
41 |
}
|
Die obige Komponente sieht wie folgt aus. Im Screenshot habe ich auf die Schaltfläche Alle Benutzer abrufen geklickt und die Ergebnisse wurden erfolgreich angezeigt.



Schritt 4: Konfigurieren eines HttpInterceptor
Wie bereits erwähnt, können Sie die Werte einer beliebigen Anfrage hinzufügen oder ändern. In einer Anwendung können Sie mehrere Interceptoren haben. Deshalb ist es wichtig, dass Sie den Interceptor als Provider in app.module.ts registrieren. Wenn der Interceptor hier nicht registriert ist, kann er die Anfragen, die wir über den HttpClient-Dienst stellen, nicht abfangen.
Einer der Interceptoren in unserem Projekt befindet sich in utility/header.interceptor.ts. Und wir müssen es in app.module.ts importieren.
1 |
import { NgModule } from '@angular/core'; |
2 |
import { BrowserModule } from '@angular/platform-browser'; |
3 |
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; |
4 |
|
5 |
import { AppRoutingModule } from './app-routing.module'; |
6 |
import { AppComponent } from './app.component'; |
7 |
import { ParentHttpService } from './parent/parent.service'; |
8 |
import { HeaderInterceptor } from './utility/header.interceptor'; |
9 |
|
10 |
@NgModule({ |
11 |
declarations: [ |
12 |
AppComponent
|
13 |
],
|
14 |
imports: [ |
15 |
BrowserModule, |
16 |
AppRoutingModule, |
17 |
HttpClientModule
|
18 |
],
|
19 |
providers: [ { provide: HTTP_INTERCEPTORS, useClass: HeaderInterceptor, multi: true }, ParentHttpService], |
20 |
bootstrap: [AppComponent] |
21 |
})
|
22 |
export class AppModule { } |
23 |
Die Syntax für das Hinzufügen von Interceptoren in Ihrer @NgModule Konfiguration lautet:
1 |
providers: [{ provide: HTTP_INTERCEPTORS, useClass: <Name des Interceptors>, multi: true }] |
Schritt 5: Erstellen des HttpInterceptors
Um einen Interceptor zu erstellen, muss die Schnittstelle HttpInterceptor, die in @angular/common/http verfügbar ist, implementiert werden. Jedes Mal, wenn Ihre Angular-Anwendung über den HttpClient-Dienst eine Anfrage stellt oder eine Antwort über das HTTP-Protokoll erhält, wird die intercept-Methode des Interceptors aufgerufen.
Die Methode intercept hat folgende Struktur:
- Input: nimmt einen Verweis auf das
httpRequestObjekt entgegen - Purpose: inspiziert und modifiziert das
httpRequestObjekt nach Bedarf - Output: ruft
next.handlemit dem modifiziertenhttpRequest
auf
Schritt 6: Abfangen des Headers
Weil wir das Abfangen gelernt haben, fügen wir allen unseren API-Anfragen einen Header hinzu. Hier fügen wir eine neue Kopfzeile namens ANGULAR_TUTS_INTERCEPTOR zu unserer get-Anfrage hinzu. Wie bereits erwähnt, können wir im Code mehrere Interceptoren verwenden. Vergessen Sie nicht, den Interceptor richtig zu benennen, damit Sie den Code besser identifizieren und pflegen können.
1 |
//app.interceptor.ts |
2 |
import { Injectable } from '@angular/core';
|
3 |
import { HttpInterceptor, HttpEvent, HttpResponse, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http';
|
4 |
import { Observable } from 'rxjs';
|
5 |
|
6 |
@Injectable() |
7 |
export class HeaderInterceptor implements HttpInterceptor {
|
8 |
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
9 |
console.log("Inside Intercept");
|
10 |
const ANGULAR_TUTS_INTERCEPTOR = '123456'; |
11 |
return next.handle(httpRequest.clone({ setHeaders: { ANGULAR_TUTS_INTERCEPTOR } }));
|
12 |
} |
13 |
} |
Hier ist ein Screenshot des Headers, der in unsere GET-Anfrage eingefügt wird.



Schritt 7: Abfangen des Antwortkörpers
Neben dem Abfangen der Kopfzeile einer Anfrage können wir auch den Antwortkörper verändern. Den Code zum Abfangen des Antwortkörpers finden Sie in response.interceptor.ts. Hier verwenden wir die HttpResponse und fügen einen neuen Parameter namens projectCode in den Body ein. Wenn die Antwort in unserer Komponente gedruckt wird, sehen Sie projectCode in der Ausgabe.
Mit dem neuen ResponseInterceptor sieht unsere app.module.ts wie folgt aus:
1 |
providers: [ |
2 |
{ provide: HTTP_INTERCEPTORS, useClass: ResponseInterceptor, multi: true },
|
3 |
{ provide: HTTP_INTERCEPTORS, useClass: HeaderInterceptor, multi: true }
|
4 |
ParentHttpService |
5 |
] |
1 |
//response.interceptor.ts
|
2 |
import { Injectable } from '@angular/core'; |
3 |
import { HttpInterceptor, HttpEvent, HttpResponse, HttpRequest, HttpHandler } from '@angular/common/http'; |
4 |
import { Observable } from 'rxjs'; |
5 |
import { map } from 'rxjs/operators' |
6 |
|
7 |
@Injectable() |
8 |
export class ResponseInterceptor implements HttpInterceptor { |
9 |
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { |
10 |
return next.handle(req).pipe( |
11 |
map((event: HttpEvent<any>) => { |
12 |
if (event instanceof HttpResponse) { |
13 |
event = event.clone({ body: this.handleResponse(event) }) |
14 |
}
|
15 |
return event; |
16 |
})
|
17 |
)
|
18 |
}
|
19 |
private handleResponse(event: any): any { |
20 |
// override http response body here
|
21 |
const body = { ...event.body, "projectCode": "angular_tuts_http" }; |
22 |
return body; |
23 |
}
|
24 |
}
|
In diesem Screenshot können Sie den Response Interceptor in Aktion sehen. Wir haben projectCode hervorgehoben, um den neu hinzugefügten Parameter in der Antwort zu zeigen.



Schritt 8: Fehler Behandlung
Interceptoren helfen uns, Fehler besser zu behandeln. Eine API gibt nicht immer das erwartete Ergebnis zurück. Manchmal, wenn der Server nicht erreichbar ist oder die Anfrage nicht den richtigen Body enthält, werden Sie zwangsläufig einen Fehler erhalten. Aus diesem Grund ist die Fehlerbehandlung extrem wichtig. In unserer Datei error.interceptor.ts haben wir eine einfache Logik für die Fehlerbehandlung hinzugefügt. Die API-Anfrage wird viermal wiederholt, bis der letzte Fehler an die Komponente ausgegeben wird.
Einer der wichtigsten Aspekte in diesem Code ist die Verwendung von RxJS. Später in diesem Tutorial werden wir sehen, warum RxJS wichtig ist.
Wir müssen app.module.ts mit dem neuen ErrorInterceptor verbessern. Die Datei sieht wie folgt aus.
1 |
providers: [ |
2 |
{ provide: HTTP_INTERCEPTORS, useClass: ResponseInterceptor, multi: true },
|
3 |
{ provide: HTTP_INTERCEPTORS, useClass: HeaderInterceptor, multi: true },
|
4 |
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
|
5 |
ParentHttpService |
6 |
] |
1 |
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
2 |
import { Injectable } from '@angular/core';
|
3 |
import { of, throwError } from 'rxjs';
|
4 |
import { concatMap, delay, retryWhen } from 'rxjs/operators';
|
5 |
|
6 |
@Injectable() |
7 |
export class ErrorInterceptor implements HttpInterceptor {
|
8 |
retryCount = 3; |
9 |
retryWaitTime = 1000; |
10 |
intercept(req: HttpRequest <any>, next: HttpHandler) {
|
11 |
return next.handle(req).pipe( |
12 |
retryWhen(error => |
13 |
error.pipe( |
14 |
concatMap((error, count) => {
|
15 |
if (count <= this.retryCount && error.status == 404) {
|
16 |
return of(error); |
17 |
} |
18 |
return throwError(error); |
19 |
}), |
20 |
delay(this.retryWaitTime) |
21 |
) |
22 |
) |
23 |
); |
24 |
} |
25 |
} |
Hier ist ein Screenshot, der das Verhalten von error.interceptor.ts. zeigt. Wie Sie sehen können, wird dieselbe API-Anfrage auf der Registerkarte Netzwerk mehrfach gestellt.



Tipps und Tricks zur Verwendung von @angular/common/http
HttpParams
HTTP Get kann mehrere Query String Parameter haben. Hier ist ein einfaches Beispiel:
1 |
https://reqres.in/api/users?page=2 |
In dem obigen Ausschnitt gibt es einen Query-String-Parameter: page = 2. Mit dem Paket @angular/common/http können Sie ganz einfach Query String Parameter hinzufügen. Um dies zu erreichen, müssen Sie HttpParams aus dem Paket importieren. HttpParams ist unveränderlich. Alle API-Methoden, die mit HttpParams verknüpft sind, führen zu keinerlei Objektveränderung. Deshalb müssen wir den Aufruf der Methode set verketten. Wenn Sie versuchen, HttpParams auf andere Weise zu setzen, wird das nicht funktionieren. Stattdessen erhalten Sie ein leeres HttpParams Objekt.
1 |
//parent.service.ts
|
2 |
import {HttpParams} from "@angular/common/http"; |
3 |
|
4 |
//CHAINING
|
5 |
const params = new HttpParams() |
6 |
.set('page', pageNo) |
7 |
|
8 |
return this.http.get(this.url, {params}) |
9 |
|
10 |
//DOES NOT WORK
|
11 |
params.set('page', 'pageNo"') |
Was würden Sie tun, wenn die URL aus vorhandenen Query-String-Parametern besteht? In diesem Fall können Sie fromString verwenden. fromString ist ein Teil von HttpParams, und hier sehen Sie, wie Sie ihn verwenden können:
1 |
const params = new HttpParams({ |
2 |
fromString: 'page=2' |
3 |
});
|
HttpHeaders
Als nächstes wollen wir verstehen, wie man HTTP-Header liest und setzt. Wenn Sie noch nicht mit HTTP vertraut sind, empfehlen wir Ihnen, unseren Post über HTTP zu lesen.
HTTP-Header machen bei jeder HTTP-Anfrage oder -Antwort einen großen Unterschied. Einige Header werden automatisch in die Anfrage eingefügt, andere können Sie selbst in die Anfrage einfügen. Um dies zu erreichen, müssen Sie die Klasse HttpHeaders aus @angular/common/http verwenden. Genau wie HttpParams ist auch HttpHeaders unveränderlich.
1 |
const headers = new HttpHeaders() |
2 |
.set("Content-Type", "application/json"); |
3 |
const params = new HttpParams() |
4 |
.set('page', pageNo) |
5 |
|
6 |
return this.http.get(this.url, {headers, params}) |
RxJS
Die Aufgabe von RxJS besteht darin, sicherzustellen, dass pro Subscription nur eine HTTP-Anfrage gestellt wird. In Ihrem Code kann es häufig zu doppelten Anfragen kommen. Dies beeinträchtigt die Leistung und kann sogar zum Abbruch Ihrer Anwendung führen. Wenn Sie möchten, dass Daten nur einmal vom Back-End abgefragt werden, sollten Sie RxJS verwenden.
Auch wenn HTTP-Anfragen parallel erfolgen und die Ergebnisse kombiniert werden müssen, können wir forkJoin aus der RxJS-Bibliothek verwenden.
Wenn Sie möchten, dass Ihre HTTP-Anfragen in einer Reihenfolge ausgeführt werden und das Ergebnis der ersten Anfrage zum Aufbau der zweiten Anfrage verwendet werden soll, können Sie switchMap verwenden. Dies sind nur zwei der häufigen Anwendungsfälle für RxJS.
Ein weiterer wichtiger Aspekt von RxJS sind die Operatoren. Diese Bibliothek bietet Operatoren wie map und filter, die zusammen mit next.handle verwendet werden können.
Abschluss
Wir sind am Ende dieses Tutorials über Angular HTTP angelangt. Das Stellen von Anfragen und das Warten auf Antworten ist ein unvermeidlicher Schritt in jeder einseitigen Anwendung. Es ist wichtig, eine skalierbare Anwendung zu bauen, die einfach zu warten ist. Nutzen Sie die Bibliothek @angular/common/http zusammen mit RxJS, um den HTTP-Workflow Ihres Clients zu erstellen.



