Skip to content Skip to sidebar Skip to footer

How To Call Promise Function In Loop And Save Its Return Value

I have created a promise function(using bluebird) called getBasketObject. This function expects a basket as an argument and than return a new basketObject out of it. basketObject h

Solution 1:

First of all your resolve(basketObj) is not valid because you call resolve multiple times for you Promise, but you must call it only once.

You also should avoid to use string as errors, but always use real error (not only with promises but all the time in javascript).

Instead of your for in loop you can pass Object.keys(productLineItems) in your Promise chain, and then use the .each instead of the for in loop.

That way you can return the Promise introduced by product.getProductObject.

You could rewrite it like that:

exports.getBasketObject = function(basket) {

  var basketObj = {};
  var productLineItems;

  returnPromise.resolve(basket)
  .then(function(basket) {
    if( !basket ) {
      thrownewError("Please give valid basket");
    }
    productLineItems = basket.product_items;
  })
  .then(function() {
    if ( 'order_total'in basket && basket.order_total) {
      basketObj.total = basket.order_total;
    } elseif ( 'product_total'in basket && basket.product_total) {
      basketObj.total = basket.product_total;
    }

    basketObj.products = {};

    //return the all keys of the productLineItems to be able to iterate over it using promisesreturnObject.keys(productLineItems);
  })
  .each(function(key) {
    var productItem = productLineItems[key];
    var productId = productItem.product_id;
    basketObj.products[productId] = {};
    basketObj.products[productId].productQuantity = productItem.quantity;
    basketObj.products[productId].productName = productItem.item_text;
    basketObj.products[productId].productPrice = productItem.base_price;

    //Async call to get Product Objectreturn product.getProductObject(productId).then(function(productObj) {
      //If promise resolved, get imagesvar imageObject = product.getProductImages(productObj[0]);
      var smallImage = imageObject.small;
      basketObj.products[productId].productImageSrc = smallImage[0];
    });
  })
  .then(function() {
    //  return the basketObj after all  product.getProductObject resolvedreturn basketObj;
  });
};

If you don't want to use .each you can write it that way:

exports.getBasketObject = function(basket) {

  var basketObj = {};
  var productLineItems;

  returnPromise.resolve(basket)
  .then(function(basket) {
    if( !basket ) {
      thrownewError("Please give valid basket");
    }
    productLineItems = basket.product_items;
  })
  .then(function() {
    if ( 'order_total'in basket && basket.order_total) {
      basketObj.total = basket.order_total;
    } elseif ( 'product_total'in basket && basket.product_total) {
      basketObj.total = basket.product_total;
    }

    basketObj.products = {};

    var promises = [];

    Object.keys(productLineItems).forEach(function(key) {
      var productItem = productLineItems[key];
      var productId = productItem.product_id;
      basketObj.products[productId] = {};
      basketObj.products[productId].productQuantity = productItem.quantity;
      basketObj.products[productId].productName = productItem.item_text;
      basketObj.products[productId].productPrice = productItem.base_price;


      promises.push(
        product.getProductObject(productId).then(function(productObj) {
          //If promise resolved, get imagesvar imageObject = product.getProductImages(productObj[0]);
          var smallImage = imageObject.small;
          basketObj.products[productId].productImageSrc = smallImage[0];
        });
      );
    });

    returnPromise.all(promises);
  })
  .then(function() {
    return basketObj;
  });
};

Solution 2:

Loop did not finished because you resolve your promise at the first iteration. But you need to wait all the async calls of product.getProductObject to finished. Here Promise.all to help.

...
var asycnCalls = [];
for (var index in productLineItems) {

    ...
    //Async call to get Product Object
    asyncCalls.push(
        product.getProductObject(productId).then(function(productObj){
            //If promise resolved, get imagesvar imageObject = product.getProductImages(productObj[0]);
            var smallImage = imageObject['small'];
            basketObj["products"][productId]["productImageSrc"] = smallImage[0];                
        })
    )
} //end of for loopPromise.all(asyncCalls).then(function(value) { 
    resolve(basketObj); //Acts as a return
}, function(reason) {
    reject(reason);
});

And please make sure product.getProductObject(productId) does really make async calls

Post a Comment for "How To Call Promise Function In Loop And Save Its Return Value"