Laurent Meyer
Laurent Meyer

Reputation: 2881

Nested Promise with lists

I'm using Parse.com to store the data of my app and I'm currently stuck with some nested promises. I'm quite new to this concept and I wrote that:

this.loadCategories = function() {
      var global = ParseService.toAngularPromise(new Parse.Query(Categories).find());
      global.then(function(categories){
        return categories.forEach(function (category){
          var criteriaPerCategory = ParseService.toAngularPromise(category.relation('relevantCriteria').query().find());
          return criteriaPerCategory.then(function (allCriteriaPerCategory){
            category._criteria = allCriteriaPerCategory;
          });
        });
      });
      return global;
    };

It nearly works... All promises are getting executed except the last one: this should be called before the view loads in Angular and it basically works except that the line category._criteria = allCriteriaPerCategory; is called after the view has been created and I do not understand why.

I know that this style for writing promises is not very academic but I didn't find any better solution because of this list... I'd very happy to get some insights about my code!

The ParseService is only a service which creates Angular Promises from normal JS Promises.

Upvotes: 0

Views: 62

Answers (3)

MinusFour
MinusFour

Reputation: 14423

Your loop is just launching promises into the wind, there's no chaining being done. You need to stack all these promises and then check when all of them are done. This can be easily done with map and $q.all. You just need to inject that dependency.

this.loadCategories = function() {
  var global = ParseService.toAngularPromise(new Parse.Query(Categories).find());
  return global.then(function(categories){
    return $q.all(categories.map(function (category){
      var criteriaPerCategory = ParseService.toAngularPromise(category.relation('relevantCriteria').query().find());
      return criteriaPerCategory.then(function (allCriteriaPerCategory){
        category._criteria = allCriteriaPerCategory;
        return category;
      });
    }));
  });
};

Upvotes: 2

Laurent Meyer
Laurent Meyer

Reputation: 2881

After a bit of time I changed strategy and ended up with that:

  this.loadCategories2 = function () {

    function loadAllData(category) {
      var relatedCriteria = category.relation('relevantCriteria').query().find().then(function (criteria) {
        category._criteria = criteria;
        return category;
      });
      return $q.when(relatedCriteria);
    }

    return ParseService.toAngularPromise(new Parse.Query(Categories).find()).then(function (categories) {
      return $q.all(categories.map(loadAllData))
    })
  }

I'm very interested in comments for that answer but it basically does what I was expecting :)

Upvotes: 1

corvid
corvid

Reputation: 11187

Try this:

categories.reduce(function (p, category) {
  return p.then(() => ParseService.toAngularPromise(category.relation('relevantCriteria').query().find()));
}, Promise.resolve()).then(function () {
  // do whatever.
});

Upvotes: 0

Related Questions