javascript - Hämta den slutliga datan från Angular-tjänst
I min Angular 6-applikation har jag en product_id som är en array,
product_id: any = ["123", "456"];ngOnInit :
ngOnInit() {
this.product_id.forEach(element => {
this.httpClient.get('https://api.myjson.com/bins/hiolc').subscribe(res => {
this.productList = [];
res.products.forEach( item => {
this.productList.push(item);
});
})
})
console.log(this.productList);
}
Här i console.log(this.productList); behöver jag ha det förväntade resultatet som,
[{
"product_name": "Product One",
"product_information": {
"template_details": [
{
"template_name": "RACE Template",
"productProperties": [
{
"property_id": 2518427931,
"property_name": "Length",
"property_value": "12 cm"
},
{
"property_id": 2621195440,
"property_name": "Width",
"property_value": "10 cm"
},
{
"property_id": 2621195441,
"property_name": "Height",
"property_value": "20 cm"
}
]
}
]
}
},
{
"product_name": "Product Two",
"product_information": {
"template_details": [
{
"template_name": "RACE Template",
"productProperties": [
{
"property_id": 2518427931,
"property_name": "Length",
"property_value": "15 cm"
},
{
"property_id": 2621195440,
"property_name": "Width",
"property_value": "12 cm"
},
{
"property_id": 2621195441,
"property_name": "Size",
"property_value": "Medium"
}
]
}
]
}
}]
Men vilket ger tom array []..
Hur man väntar på att tjänsten ska slutföras och sedan lagrar datan i productList..
Jag behöver forEach, this.product_id.forEach(element eftersom i min verkliga applikation baserat på foreach kommer jag att få produktlistan för varje produkt-id som skickas via url..
Vänligen hjälp mig att lagra data efter avslutad hela tjänsten baserat på forEach efter att alla produkt-ID har skickats och sedan få den slutliga produktlistan..
Arbetande stackblitz: https://stackblitz.com/edit/flatternstructure-dvzpjv
Återigen klargör jag att i min riktiga applikation behöver jag skicka id:t för att få produktvärdet som https://api.myjson.com/bins/hiolc + element..
Också, om jag får den slutliga productList så behöver jag göra en annan funktionalitet med den slutliga productList, så jag förväntar mig bara komplett data i productList till sist och inte inne i forEach..
Svar #1
använd rxjs.concat :
[redigera]
tillgänglig på stackblitz
...
import { concat } from 'rxjs';
import { map } from 'rxjs/operators';
...
ngOnInit() {
this.productList = [];
concat(
this.product_id.map(
element => this.httpClient.get('https://api.myjson.com/bins/hiolc')
)
).pipe(
map((res: any) => this.productList = this.productList.concat(res.products))
).subscribe(res => {
console.log(res);
console.log(this.productList);
});
}
Hoppas det hjälper.
Svar #2
Du har två problem: du loggar det för tidigt, och du skriver över arrayen.
Först, loggen kommer för snart. Du skickar iväg förfrågningar (ids.forEach(id => this.http....)). Sedan direkt efter det, gör du en console.log - men resultaten har inte kommit tillbaka än. Förfrågningarna har troligen inte ens skickats än. Därför ser du den tomma arrayen. Flytta console.log-satsen direkt under this.productList.push(...)-satsen, så kommer du att se resultatet.
Det andra problemet är att du skickar parallella förfrågningar och de båda återställer produktlistan med den här raden: this.productList=[];.
Du vill bara göra det en gång.
En bättre version av detta allt skulle vara:
ngOnInit() {
forkJoin(product_ids) // fire them in parallel.
.pipe(
map(id => this.http.get('https://api.myjson.com/bins/hiolc' + id)), // fetch the things
map(items=> this.productList = this.productList.concat(items)),
)
.subscribe(() => console.log('Done, items:', this.productList));
En ännu bättre version skulle vara:
ngOnInit() {
this.someService.getProductItems(productIds)
.subscribe(productList => this.productList = productList);
}
Det betyder att du ska flytta dina Http-anrop till en tjänst, göra allt detta där, och hålla din komponent renare och enklare.
