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.