1

I understand using promises in simple scenarios but currently really confused on how to implement something when using a for loop and some updates to local sqlite database.

Code is as follows

surveyDataLayer.getSurveysToUpload().then(function(surveys) {
  var q = $q.defer();

  for (var item in surveys) {
    var survey = surveys[item];

    // created as a closure so i can pass in the current item due to async process
    (function(survey) {
      ajaxserviceAPI.postSurvey(survey).then(function(response) {
        //from response update local database
        surveyDataLayer.setLocalSurveyServerId(survey, response.result).then(function() {
          q.resolve; // resolve promise - tried only doing this when last record also
        })
    });
    })(survey) //pass in current survey used to pass in item into closure


  }

  return q.promise;

}).then(function() {
  alert('Done'); // This never gets run
});

Any help or assistance would be appreciated. I'm probably struggling on how best to do async calls within loop which does another async call to update and then continue once completed.

at least promises have got me out of callback hell.

Cheers

1
  • What you are looking for is $q.all and pass in an array of promises that you can create via a for-loop. Commented Oct 9, 2015 at 6:12

3 Answers 3

5

This answer will get you laid at JS conferences (no guarantees though)

surveyDataLayer.getSurveysToUpload().then(function(surveys) {
    return Promise.all(Object.keys(surveys).map(function(key) {
        var survey = surveys[key];
        return ajaxserviceAPI.postSurvey(survey).then(function(response){
            return surveyDataLayer.setLocalSurveyServerId(survey, response.result);
        });
    }));
}).then(function() {
    alert('Done');
});
Sign up to request clarification or add additional context in comments.

1 Comment

LOL. nice, neat way was just reading up on map also.... ill show it the wife tonight who knows! may get lucky :)
2

This should work (explanations in comments):

surveyDataLayer.getSurveysToUpload().then(function(surveys) {
  // array to store promises
  var promises = []; 

  for (var item in surveys) {
    var survey = surveys[item];

    // created as a closure so i can pass in the current item due to async process
    (function(survey) {
      var promise = ajaxserviceAPI.postSurvey(survey).then(function(response){
        //returning this promise (I hope it's a promise) will replace the promise created by *then*
        return surveyDataLayer.setLocalSurveyServerId(survey, response.result);
      });
      promises.push(promise);
    })(survey); //pass in current survey used to pass in item into closure
  }
  // wait for all promises to resolve. If one fails nothing resolves.
  return $q.all(promises);

}).then(function() {
  alert('Done');
});

Awesome tutorial: http://ponyfoo.com/articles/es6-promises-in-depth

6 Comments

This is correct, but I strongly suggest adding some explanation, and not just a code-only answer
Thanks for quick response , I had something similar before but even with the code above in my console log it ends up showing the alert part before the posts. I looked i console log and was expecting the postSurvey console logs where it resolved to be before the done one once everything completes , does that make sense ?
Think its ok , I moved the line promises.push(promise); after the }); Thanks for the help.
umm .. where did you move it ? :)
looks like you updated it... or I had a typo.. I can enjoy my weekend now as after 2 hours i was losing hope. thanks sirroco
|
1

You basically want to wait for all of them to finish before resolving getSurveysToUpload, yes? In that case, you can return $q.all() in your getSurveysToUpload().then()

For example (not guaranteed working code, but you should get an idea):

surveyDataLayer.getSurveysToUpload().then(function(surveys) {
  var promises = [];

  // This type of loop will not work in older IEs, if that's of any consideration to you
  for (var item in surveys) {
    var survey = surveys[item];

    promises.push(ajaxserviceAPI.postSurvey(survey));
  }

  var allPromise = $q.all(promises)
    .then(function(responses) {
      // Again, we want to wait for the completion of all setLocalSurveyServerId calls
      var promises = [];
      for (var index = 0; index < responses.length; index++) {
        var response = responses[index];

        promises.push(surveyDataLayer.setLocalSurveyServerId(survey, response.result));
      }

      return $q.all(promises);
    });

  return allPromise;
}).then(function() {
  alert('Done'); // This never gets run
});

Comments

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.