typescript - Angular - Hantera HTTP-svar med DTO
Jag verkar inte kunna hitta ett komplett exempel på hur man hanterar ett komplext Angular HTTP-svar. Jag använder Angular 16.
Backend-API:t jag försöker kommunicera med tillhandahåller ett DTO (Dataöverföringsobjekt) som detta:
{
"data": {
"name": "joe",
"age": 40
},
"success": true,
"message": "completed successfully"
}
I Angular förväntar jag mig att:
- Använd HttpClient för att hämta datan
- Ha ett if-uttryck för att kontrollera HTTP-statusen
- Om 200 OK - Gör någon form av kartläggning av JSON-data till en modell
- Annars returnera ett felmeddelande till frontenden
- Returnera ett observerbart
Mina egna försök har misslyckats, men här är vad jag har just nu:
Modeller/http_response.ts:
export interface HttpResponse {
status: string;
data: any;
success: string;
message: string;
}
Modeller/user.ts:
export interface User {
name: string;
age: number;
}
Tjänster/api.service.ts:
import { HttpClient } from '@angular/common/http';
import { HttpResponse } from '../models/http_response';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor( private http: HttpClient ){ }
getData(): Observable<HttpResponse> {
// This definently is not correct
return this.http.get(`${your_api_url}/Data`, {observe:'response'}).pipe(map((res: any) => {
if(res){
console.log(`inflow_data.service - 200 OK`);
result = { status: res.status, data: res.Data.json(), success: res.Success, message: res.Message}
}
else {
console.log(`inflow_data.service - Error! HttpStatus: ${res.status}`);
result = { status: res.status, data: undefined, success: res.Success, message: res.Message}
}
}).subscribe(result => { return result });
}
}
sidor/sida1/sida1.component:
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../services/api.service'
import { HttpResponse } from '../models/http_response';
import { User } from '../models/user';
@Component({
selector: 'app-page1',
templateUrl: './page1.component.html',
styleUrls: ['./page1.component.scss']
})
export class Page1 implements OnInit {
// I should be able to grab the data from the Observable and feed it into a table or whatever
dataSource: User[] = [];
constructor(private apiService: ApiService) { }
async ngOnInit() {
this.onGetData();
}
onGetData():void {
this.apiService.getData().subscribe((response: HttpResponse) => {
console.log(`Http response was - Status: ${response.status} Success: ${response.success} Data: ${response.data}`);
if(response.success){
this.dataSource = response.data;
}
});
}
}
Du kan på sätt och vis se vad jag försöker göra. Det finns förmodligen flera saker som är fel med koden ovan. Som jag sa, jag kunde inte hitta ett komplett exempel.
Tack!
Svar #1
Det finns några fel i din kod:
I
getData-metoden bör du inte prenumerera på Observable medan din metod förväntas returneraObservable<HttpResponse>.Du får felaktigt responsens innehåll. Eftersom du använder
{observe:'response'}, för att få innehållet i responsen bör du användares.body. En annan fråga är att se till att fältnamnet du försökte hämta från responsens innehåll måste vara exakt samma, vilket är gemener enligt det bifogade JSON-exemplet.
Uppdaterad: Med observe: "response" som kommer att resultera i en Observable<HttpResponse> (HttpResponse från @angular/common/http), kan du använda ok-egenskapen för att kontrollera om svaret är framgångsrikt (statuskod med 2XX).
- Ditt
data-fält från JSON är ett objekt, du kan inte tilldela det tilldataSourcesom är en array. Istället bör du lägga till objektet i arrayen medArray.push().
api.service.ts
getData(): Observable<HttpResponse> {
return this.http.get(`${your_api_url}/Data`, {observe:'response'}).pipe(
map((res: any) => {
let responseBody = res?.body;
let result: HttpResponse;
if (res.ok) {
console.log(`inflow_data.service - 200 OK`);
result = {
status: res.status,
data: responseBody.data,
success: responseBody.success,
message: responseBody.message,
};
} else {
console.log(`inflow_data.service - Error! HttpStatus: ${res.status}`);
result = {
status: res.status,
data: undefined,
success: responseBody?.success,
message: responseBody?.message,
};
}
return result;
})
);
}
page1.komponent
this.apiService.getData().subscribe((response: HttpResponse) => {
console.log(
`Http response was - Status: ${response.status} Success: ${response.success} Data: ${response.data}`
);
if (response.success) {
this.dataSource.push(response.data);
}
});
Demo @ StackBlitz
