koque
koque

Reputation: 2256

Accessing data returned by Promise.all

In the service method below, I pass two parallel queries to the server using Promise.all. The results are returned and stored in the productCategoryData array. This array is logged to the console and the data is verified.

Service method

public getProductCategoryData() {
var productCategoryData = [];

return Promise.all([this.http.get(this.specialValueUrl), 
  this.http.get(this.applianceBrandUrl)])
.then(function(responses) {
  responses[0].toPromise().
    then(response => {
      let specialvalues: SpecialValue[] = response.json();
      productCategoryData[0] = specialvalues;
      // console.log(specialvalues)
    });

  responses[1].toPromise().
    then(response => {
      let applianceBrands: ApplianceBrand[] = response.json();
      productCategoryData[1] = applianceBrands;
      // console.log(applianceBrands)
    });        

  return productCategoryData;
})
  }

The productCategoryData array is then passed to the component where it is once again logged to the console. I then assign the data of the productCategoryData array to two arrays defined in the component: this.specialValues and this.applianceBrands. But they are undefined when logged to the console. I expect these arrays to have data.

Component method:

private getProductCategoryData() {
this.productCategoryService.getProductCategoryData()
.then(productCategoryData => {
  this.specialValues = productCategoryData[0];
  this.applianceBrands = productCategoryData[1];

  console.log('productCategory.Data = ', productCategoryData) //has data
  console.log('this.specialValues = ', this.specialValues) //undefined
  console.log('this.applianceBrands = ', this.applianceBrands) //undefined

});
  }

Upvotes: 0

Views: 54

Answers (2)

trincot
trincot

Reputation: 350252

You are returning productCategoryData before you have assigned the asynchronous response to it via the two inner then callbacks.

Instead, convert to promises before applying Promise.all and then use map to apply the json method to the results:

return Promise.all([this.specialValueUrl, this.applianceBrandUrl].map(url =>
    this.http.get(url).toPromise()
).then(responses => responses.map(response => response.json()));

Upvotes: 1

rjustin
rjustin

Reputation: 1439

Your issue is within the service. There are a couple things going on here.

  • http.get returns an Observable. This must be subscribed to or converted to a Promise.
  • Promise.all() will work normally for promises but will just pass in what it was given for anything else(like an Observable or variables etc.)

To fix this just convert your Observables (http.get()) to Promises and return that.

Due to you passing observables to promise.all() it made it seem like you needed to then convert the results themselves to promises in the call back but that is unnecessary.

this is all you need:

service:

public getProductCategoryData() {
   return Promise.all([this.http.get(this.specialValueUrl).toPromise(), 
    this.http.get(this.applianceBrandUrl).toPromise()])

}

component:

private getProductCategoryData() {
this.productCategoryService.getProductCategoryData()
  .then(productCategoryData => {
      this.specialValues = productCategoryData[0];
      this.applianceBrands = productCategoryData[1];

      console.log('productCategory.Data = ', productCategoryData) //has data
      console.log('this.specialValues = ', this.specialValues) //undefined
      console.log('this.applianceBrands = ', this.applianceBrands) //undefined

    });
  }

Upvotes: 1

Related Questions