Cereri HTTP
Angular poate comunica prin intermediul HTTP Requests/Responses catre un Server (API - REST, GraphQL) care la randul sau comunica cu o baza de date.
Documentatia oficiala aici.
Documentatia oficiala aici.
Cererea HTTP:
- URL
- HTTP verb: POST, GET, PUT
- Headers (metadata): {"Content-Type" : "application/json"}
- Body: {title : "New Post"}
Solutie de serviciu backend: Firebase de la Google
- Realtime database (start in test mode)
- URL-ul furnizat poate fi URL-ul la care se pot trimite cereri din Angular
Pasi pentru a folosi HttpClient:
1. app.module.ts -> imports -> HttpClientModule
2. HttpClient se injecteaza in constructorul clasei unde dorim sa-l folosim
3. Trimiterea unei cereri de POST: this.httpClient.post(url: String, postData: object);
// in functie de url, Firebase va aseza datele intr-o structura de dosare
// postData va fi convertit automat intr-un json
!!! post() intoarce un Observable. Simpla chemare a lui post() nu va declansa nimic, dupa principiul: daca nimeni nu este interesat (= subscription), nu se executa. Asadar:
this.httpClient.post(url: String, postData: object).subscribe(responseData => {
// do something
});
// nu este nevoie de unsubscribe() pentru ca este un Observable administrat de Angular
GET
this.httpClient.get(url).subscribe(posts => {
// do something
});
Prelucrarea datelor:
this.httpClient
.get(url)
.pipe(map(post => {
// prelucreaza & return data
}))
.subscribe(posts => {
// do something
});
Tipizare:
this.httpClient
.get<{ [key: string]: Post }>(url)
.pipe(map(post => {
// process & return data
}))
.subscribe(posts => {
// do something
});
- unde: [key: string] inseamna orice proprietate cu rol de cheie (nu ii cunoastem numele, este generata la intamplare de Firebase), iar Post este tipul valorii furnizate de aceasta bucata de date
- tipizarea este valabila si pentru alte metode, cum ar fi post()
Se recomanda ca actiunile Http sa se realizeze in servicii.
- fie adnotate cu @Injectable({providedIn: 'root'})
- fie se inscriu in app.module.ts -> providers
- se poate face subscribe concomitent in serviciu (pentru ca actiunea sa se execute), si in componenta care cheama serviciul (doar daca o intereseaza raspunsul)
DELETE
this.httpClient.delete(url, object).subscribe( () => { // empty response
// here you can set up some flags
});
!!! Pentru separarea intre componenta/serviciu, in serviciu se face delete (fara subscribe), iar in componenta se menajeaza variabilele.
Tratarea erorilor:
error: String;
// ...
this.httpClient.get(url).subscribe(posts => {
// do something
this.error = null;
}, error => {
this.error = error.message;
});
Alt mod de a trata erorile, in serviciu:
error = new Subject<string>();
this.httpClient.post(url, postData).subscribe(responseData => {
// ..
}, error => {
this.error.next(error.message);
});
In componenta, in ngOnInit():
this.service.error.subscribe(errorMessage -> {
this.error = errorMessage;
});
// in acest caz se cuvine sa faci unsubscribe, in ngOnDestroy()
Operatorul catchError:
this.httpClient
.get(url)
.pipe(map(post => {
// prelucreaza & return data
}), catchError(errorRes => {
// generic error handling task, like logging / analytics
throwError(errorRes); // it needs to be able to reach subscribe again
}))
.subscribe(posts => {
// do something
});
Antete, query params
this.httpClient.get(url, {
headers: new HttpHeaders({'Custom-Header': 'Hello'}),
params: new HttpParams().set('print', 'pretty') // echivalent cu url/page.json?print=pretty
}); // pt GET antetul trimis va fi al doilea argument
Alternativ, pentru query params:
let searchParams = new HttpParams(); // obiect imutabil
searchParams = searchParams.append('print', 'pretty');
searchParams = searchParams.append('custom', 'key');
// params: searchParams
Observare:
this.httpClient.post(url, data, {observe: 'response'}); // response, body, events
this.httpClient
.delete(url, {observe: 'events'})
.pipe(tap(event => { // tap nu intrerupe felul cum decurge observabilul, primeste doar events
if (event.type === HttpEventType.Response) { // verifica daca raspunsul s-a primit
console.log(event.body);
}
}));
Schimbarea tipului de raspuns:
this.httpClient
.delete(url, {
observe: 'events',
responseType: 'json' // text, blob, etc
})
Interceptori
export class AuthInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
// next e o functie
console.log('Request is on its way');
return next.handle(req); // let the request leave the app
}
}
In app.module.ts -> providers -> [{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorService, multi: true}]
Manipulare Request (care este imutabil):
const modifiedRequest = req.clone({
headers: req.headers.append('Auth': 'xyz')
});
return next.handle(modifiedRequest);
Interceptori pentru raspuns - in return se manipuleaza raspunsul:
return next.handle(req).pipe(tap(event => {
if (event.type === HttpEventType.Response) {
// console.log (event.body);
}
}));
2. HttpClient se injecteaza in constructorul clasei unde dorim sa-l folosim
3. Trimiterea unei cereri de POST: this.httpClient.post(url: String, postData: object);
// in functie de url, Firebase va aseza datele intr-o structura de dosare
// postData va fi convertit automat intr-un json
!!! post() intoarce un Observable. Simpla chemare a lui post() nu va declansa nimic, dupa principiul: daca nimeni nu este interesat (= subscription), nu se executa. Asadar:
this.httpClient.post(url: String, postData: object).subscribe(responseData => {
// do something
});
// nu este nevoie de unsubscribe() pentru ca este un Observable administrat de Angular
GET
this.httpClient.get(url).subscribe(posts => {
// do something
});
Prelucrarea datelor:
this.httpClient
.get(url)
.pipe(map(post => {
// prelucreaza & return data
}))
.subscribe(posts => {
// do something
});
Tipizare:
this.httpClient
.get<{ [key: string]: Post }>(url)
.pipe(map(post => {
// process & return data
}))
.subscribe(posts => {
// do something
});
- unde: [key: string] inseamna orice proprietate cu rol de cheie (nu ii cunoastem numele, este generata la intamplare de Firebase), iar Post este tipul valorii furnizate de aceasta bucata de date
- tipizarea este valabila si pentru alte metode, cum ar fi post()
Se recomanda ca actiunile Http sa se realizeze in servicii.
- fie adnotate cu @Injectable({providedIn: 'root'})
- fie se inscriu in app.module.ts -> providers
- se poate face subscribe concomitent in serviciu (pentru ca actiunea sa se execute), si in componenta care cheama serviciul (doar daca o intereseaza raspunsul)
DELETE
this.httpClient.delete(url, object).subscribe( () => { // empty response
// here you can set up some flags
});
!!! Pentru separarea intre componenta/serviciu, in serviciu se face delete (fara subscribe), iar in componenta se menajeaza variabilele.
Tratarea erorilor:
error: String;
// ...
this.httpClient.get(url).subscribe(posts => {
// do something
this.error = null;
}, error => {
this.error = error.message;
});
Alt mod de a trata erorile, in serviciu:
error = new Subject<string>();
this.httpClient.post(url, postData).subscribe(responseData => {
// ..
}, error => {
this.error.next(error.message);
});
In componenta, in ngOnInit():
this.service.error.subscribe(errorMessage -> {
this.error = errorMessage;
});
// in acest caz se cuvine sa faci unsubscribe, in ngOnDestroy()
Operatorul catchError:
this.httpClient
.get(url)
.pipe(map(post => {
// prelucreaza & return data
}), catchError(errorRes => {
// generic error handling task, like logging / analytics
throwError(errorRes); // it needs to be able to reach subscribe again
}))
.subscribe(posts => {
// do something
});
Antete, query params
this.httpClient.get(url, {
headers: new HttpHeaders({'Custom-Header': 'Hello'}),
params: new HttpParams().set('print', 'pretty') // echivalent cu url/page.json?print=pretty
}); // pt GET antetul trimis va fi al doilea argument
Alternativ, pentru query params:
let searchParams = new HttpParams(); // obiect imutabil
searchParams = searchParams.append('print', 'pretty');
searchParams = searchParams.append('custom', 'key');
// params: searchParams
Observare:
this.httpClient.post(url, data, {observe: 'response'}); // response, body, events
this.httpClient
.delete(url, {observe: 'events'})
.pipe(tap(event => { // tap nu intrerupe felul cum decurge observabilul, primeste doar events
if (event.type === HttpEventType.Response) { // verifica daca raspunsul s-a primit
console.log(event.body);
}
}));
Schimbarea tipului de raspuns:
this.httpClient
.delete(url, {
observe: 'events',
responseType: 'json' // text, blob, etc
})
Interceptori
export class AuthInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
// next e o functie
console.log('Request is on its way');
return next.handle(req); // let the request leave the app
}
}
In app.module.ts -> providers -> [{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorService, multi: true}]
Manipulare Request (care este imutabil):
const modifiedRequest = req.clone({
headers: req.headers.append('Auth': 'xyz')
});
return next.handle(modifiedRequest);
Interceptori pentru raspuns - in return se manipuleaza raspunsul:
return next.handle(req).pipe(tap(event => {
if (event.type === HttpEventType.Response) {
// console.log (event.body);
}
}));
Niciun comentariu:
Trimiteți un comentariu