0

I'm trying to pass a result (array) from a promise to a function that iterates over this result, making a get request for each item and creating a new object with the results before returning it. The problem is that the object is being returned before the promises are resolved and populate it. What is the correct way to return a populated object from multiple promises?

function getPackageDetails(packages) {
  var detailedPackages = {};
  angular.forEach(packages, function(p) {
    vsmsPackageFactory.getPackage(p.id)
    .then(function(response) {
      var subsystem = response.data.packageManifest.subsystem;
      var partNumber = response.data.packageManifest.resultConfig.partNumber;
      var packageName = response.data.packageMetaData.packageName;
      if(detailedPackages[subsystem] === undefined) {
        detailedPackages[subsystem] = {};
      }
      if(detailedPackages[subsystem][partNumber] === undefined) {
        detailedPackages[subsystem][partNumber] = {};
      }
      detailedPackages[subsystem][partNumber][packageName] = response.data;
    });
  });
  return detailedPackages; // returns before all promises resolved
}

vsmsCampaignFactory.getCampaignPackages(queryString)
.then(function(response) {
  vm.packageList = getPackageDetails(response.results);
});

2 Answers 2

2

You should consider using $q.all for such cases where you can gather up all the promises in single array of promise and then pass it in $q.all & return resultant promise. It will ensure that you're returning data after all promises are done.

In your code, you're just executing your asynchronous ajax calls without worrying about whether they are completed or not. And right after that you're returning detailedPackages data. But obvious it is gonna be empty.

Code

function getPackageDetails(packages) {
  var detailedPackages = {};
  var promises = []; //promise array
  angular.forEach(packages, function(p) {

    var promise = vsmsPackageFactory.getPackage(p.id)
    .then(function(response) {
      var subsystem = response.data.packageManifest.subsystem;
      var partNumber = response.data.packageManifest.resultConfig.partNumber;
      var packageName = response.data.packageMetaData.packageName;
      if(detailedPackages[subsystem] === undefined) {
        detailedPackages[subsystem] = {};
      }
      if(detailedPackages[subsystem][partNumber] === undefined) {
        detailedPackages[subsystem][partNumber] = {};
      }
      detailedPackages[subsystem][partNumber][packageName] = response.data;
    });
    promises.push(promise);
  });
  return $q.all(promises).then(function(){
    return detailedPackages;  // returned data after all promises are done
  });
}
Sign up to request clarification or add additional context in comments.

1 Comment

Promises are still a bit confusing for me, thanks for the help.
1

this could be achive using promise all, here.

 var promises = [];
 promises.push(new Promise(function (resolve, reject) {
   vsmsPackageFactory.getPackage(p.id)
    .then(function(response) {
     ...
     resolve('If you want to return something')
    });
 });
 //After the loop it's finished you execute your promises
 Promise.all(promises).then(function (values) {
  ... perform more code
 });

1 Comment

Thanks for the help with this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.