循环角度的承诺混淆

时间:2015-10-09 06:08:10

标签: javascript angularjs asynchronous promise

我理解在简单场景中使用promises但是当前在使用for循环和对本地sqlite数据库进行一些更新时如何实现某些东西时确实很困惑。

代码如下

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
});

任何帮助或帮助将不胜感激。我可能正在努力研究如何最好地在循环内执行异步调用,这会进行另一次异步调用以进行更新,然后在完成后继续。

至少承诺让我摆脱了回调地狱。

干杯

3 个答案:

答案 0 :(得分:5)

这个答案将让你在JS会议上做好准备(尽管不保证)

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');
});

答案 1 :(得分:2)

这应该有用(评论中的解释):

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');
});

很棒的教程:http://ponyfoo.com/articles/es6-promises-in-depth

答案 2 :(得分:1)

你基本上想要在解决getSurveysToUpload之前等待所有人完成,是吗?在这种情况下,您可以在$q.all()

中返回getSurveysToUpload().then()

例如(不保证工作代码,但你应该知道):

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
});