typescript - Angular: mappa svar från tjänst


Jag har arbetat med angular4 ett tag och hanterat JSON-svar från tjänsten. Men idag observerade jag att min tjänst returnerar mig ett svar som detta.

info-svar.json

{
"1":{
     "id":"1",
     "name":"Anna"
    },
"2":{
     "id":"2",
     "name":"Martin"
    }
}

Jag googlade det och fann att det är en map, men hur läser jag denna typ av svar, jag kan inte iterera det. Jag skrev en tjänst som nedan.

modell är Info.ts

export interface Info{
  id: string;
  name: string;
}

ts-fil är:

infoData: Info;
this.groupService.fetchInfo().subscribe(data => {
 this.infoData = data;
 // how to iterate this.infoData
});

service är:

fetchInfo(): Observable<Info>{
 const url = "/assets/info-response.json"; //as of now I am working on hard coded json as I dont know my map logic is correct of not
 //const url = "/info/getInfo";
 return this.httpClient.get<Info>(url).map(function (data => Info){
   return data;
  });
}

Jag har ingen förståelse för map och jag är inte ens säker på om min kod är korrekt eller inte. Jag har inte försökt kontakta tjänsten än och jag arbetar på den hårdkodade JSON, som nämnts ovan. Vänligen vägled mig:

Är mitt sätt att anropa tjänsten rätt, hantera karta? Hur itererar man denna typ av svar?

Svar #1

Ja, du ringer tjänsten på rätt sätt.

När det gäller map är det bästa sättet att tänka på det i ditt fall att RxJS:s map itererar över förfrågningarna när de kommer in och transformerar dem som en helhet. Varje tjänsteanrop du gör kommer att returnera ett svar. Om din avsikt är att transformera detta svar, då ja, använd RxJs map-operatorn som ovan och utför den transformation du behöver på det server-mottagna dataobjektet. Här är ett exempel som transformerar ditt serverhämtade dataobjekt från en hash till en array genom att använda RxJs map-operatorn:

// Returned data by the api call
// {
// "1":{
//      "id":"1",
//      "name":"Anna"
//     },
// "2":{
//      "id":"2",
//      "name":"Martin"
//     }
// }

fetchInfo(): Observable<Info> {
 const url = "/assets/info-response.json";
 return this.httpClient.get<Info>(url)
  .map((data: Info) => {
    // in here, data is equal to your returned JSON above
    // So, if you wish to turn this into an array
    
    const transformedData = Object.keys(data).map(key => data[key]);
    
    // as you return this output, any operator applied below,
    // as well as the data that will reach your subscribe resolver
    // will look like:
    //
    // [
    //  { "id":"1", "name":"Anna" }
    //  { "id":"2", "name":"Martin" }
    // ]
    
    reuturn transformedData;
  });
}

// As for processing the response now that it is an array...

fetchInfo().subscribe(data => {
  this.infodata = data.map(value => ({ ...value, city: 'Amsterdam' }));
  
  // your infodata object will now look like this:
  //
  // [
  //  { "id":"1", "name":"Anna", "city": "Amsterdam" }
  //  { "id":"2", "name":"Martin", "city": "Amsterdam" }
  // ]
});

Om du däremot är nöjd med svaret som det returneras av servern, finns det ingen anledning att använda map-operatorn på det eftersom det är överflödigt. Ditt tjänsteanrop kommer då helt enkelt att bli:

return this.httpClient.get<Info>(url);

Några användbara referenser: Object.keys(), Array.map()-metoden används för att transformera din resultatarray, RxJs:s map-operator används på dina API-anrop.

Och en enkel, rak lösning utan demokod, som gör exakt samma sak som koden ovan:

fetchInfo(): Observable<Info> {
 return this.httpClient.get<Info>("/assets/info-response.json");
}

fetchInfo().subscribe(data => {
  this.infodata = data.keys(key => data[key]).map(value => ({ ...value, city: 'Amsterdam' }));
});

Var uppmärksam, från och med RxJs 5 används inte längre map-operatören direkt på observabeln, utan via piping.

Hjälper detta?

Redigera:

Eftersom Object.values ännu inte är helt stödd, använde jag istället Object.keys.

Redigera 2:

La till en enkel lösning, utan demokod för att förklara RxJs map

Relaterade artiklar