javascript - Angular : chaining promises over forEach loop

标签 javascript angularjs promise angular-promise

我无法理解 promise 。我正在使用 Google Earth API 进行地址“游览”。游览只是一个持续大约一分钟的动画,一个完成后,下一个应该开始。

这是我的巡视功能:

var tourAddress = function (address) {
        return tourService.getLatLong(address).then(function (coords) {
            return tourService.getKmlForCoords(coords).then(function (kml) {
                _ge.getTourPlayer().setTour(kml);
                _ge.getTourPlayer().play();

                var counter = 0;
                var d = $q.defer();
                var waitForTour = function () {
                    if (counter < _ge.getTourPlayer().getDuration()) {
                        ++counter;
                        setTimeout(waitForTour, 1000);
                    } else {
                        d.resolve();
                    }
                };

                waitForTour();

                return d.promise;
            });
        });
    }

这似乎工作得很好。它启动动画并返回一个在动画完成时解析的 promise 。现在我有一组地址,我想对每个地址进行一次游览:

$scope.addresses.forEach(function (item) {
      tourAddress(item.address).then(function(){
          $log.log(item.address + " complete");
       });
 });

当我执行此操作时,它们会同时执行(Google Earth 会为最后一个地址制作动画)并且它们会同时完成。我如何在前一个完成后将它们链接起来触发?

更新

我在@phtrivier 的大力帮助下实现了它:

 $scope.addresses.reduce(function (curr,next) {
      return curr.then(function(){
            return tourAddress(next.address)
      });
  }, Promise.resolve()).then(function(){
      $log.log('all complete');
  });

最佳答案

你是对的,请求会立即完成,因为调用 tourAddress(item.address) 会执行一个请求并且在请求完成后返回一个已解决的 Promise。

由于您在循环中调用 tourAddress,因此会生成许多 Promise,但它们并不相互依赖。

你想要的是调用tourAdress,获取返回的Promise,等待它被解决,然后用另一个地址再次调用tourAddress,等等。

手动,你必须写这样的东西:

tourAddress(addresses[0])
  .then(function () {
     return tourAddress(addresses[1]);
  })
  .then(function () {
     return tourAddress(addresses[2]);
  })
  ... etc...

如果您想自动执行此操作(您不是第一个:How can I execute array of promises in sequential order?),您可以尝试将地址列表缩减为将执行整个链的单个 Promise。

_.reduce(addresses, function (memo, address) {

   return memo.then(function (address) {
         // This returns a Promise
         return tourAddress(address);   
   });

}, Promise.resolve());

(这是伪代码,使用下划线,和bluebird,但应该是可适配的)

关于javascript - Angular : chaining promises over forEach loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26124931/

相关文章:

javascript - 如何使用angular js将表格行添加为模板

javascript - 如何从 Javascript 数组中获取两个最大的整数并将值返回给 DOM?

javascript - 如何使用 Javascript 从 URL 中抓取任何段?

javascript - angularjs - 无法预先选择 list 模型中的复选框

javascript - 设置 angular-ui bootstrap datepicker 接受英国日期输入 (dd MM yyyy)

javascript - Promise 应该被错误或字符串拒绝吗?

javascript - 为什么 Promise 构造函数需要一个执行器?

javascript - 在循环中多次调用函数后执行promise.then

javascript - 禁用按钮上禁用表单并更改文本

javascript - 使用 Jquery close() 函数获取距离 SVG 节点最近的元素