【问题标题】:Promises for loop angular confused对循环角度混淆的承诺
【发布时间】:2015-10-09 14:56:06
【问题描述】:

我了解在简单场景中使用 Promise,但目前对于如何在使用 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
});

任何帮助或帮助将不胜感激。我可能正在为如何最好地在循环中执行异步调用而苦苦挣扎,该循环执行另一个异步调用来更新,然后在完成后继续。

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

干杯

【问题讨论】:

  • 您正在寻找的是$q.all 并传入一组您可以通过for循环创建的promise。

标签: javascript angularjs asynchronous promise


【解决方案1】:

这个答案会让你在 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');
});

【讨论】:

  • 哈哈。好,整洁的方式只是在地图上阅读......今晚我会告诉妻子,谁知道呢!可能会很幸运:)
【解决方案2】:

这应该有效(cmets 中的解释):

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

【讨论】:

  • 这是正确的,但我强烈建议添加一些解释,而不仅仅是代码答案
  • 感谢您的快速响应,我之前也有类似的情况,但即使在我的控制台日志中使用上面的代码,它最终也会在帖子之前显示警报部分。我查看了控制台日志,并期待 postSurvey 控制台日志在一切完成后在完成之前解决,这有意义吗?
  • 觉得没问题,我移动了 promises.push(promise);之后 });感谢您的帮助。
  • 嗯..你把它移到哪里去了? :)
  • 看起来你更新了它......或者我有一个错字......我现在可以享受我的周末了,因为 2 小时后我失去了希望。谢谢sirroco
【解决方案3】:

您基本上希望在解决getSurveysToUpload 之前等待所有这些都完成,是吗?在这种情况下,您可以在 getSurveysToUpload().then() 中返回 $q.all()

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    相关资源
    最近更新 更多