Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 让angular.forEach在进入下一个对象后等待承诺_Javascript_Angularjs_Foreach_Promise_Angular Promise - Fatal编程技术网

Javascript 让angular.forEach在进入下一个对象后等待承诺

Javascript 让angular.forEach在进入下一个对象后等待承诺,javascript,angularjs,foreach,promise,angular-promise,Javascript,Angularjs,Foreach,Promise,Angular Promise,我有一个物品清单。对象被传递给延迟函数。我只想在上一次调用解决后,使用下一个对象调用函数。我有什么办法可以做到这一点吗 angular.forEach(objects, function (object) { // wait for this to resolve and after that move to next object doSomething(object); }); 检查角度上的$q: function outerFunction() { var defe

我有一个物品清单。对象被传递给延迟函数。我只想在上一次调用解决后,使用下一个对象调用函数。我有什么办法可以做到这一点吗

angular.forEach(objects, function (object) {
    // wait for this to resolve and after that move to next object
    doSomething(object);
});
检查角度上的$q:

function outerFunction() {

  var defer = $q.defer();
  var promises = [];

  function lastTask(){
      writeSome('finish').then( function(){
          defer.resolve();
      });
  }

  angular.forEach( $scope.testArray, function(value){
      promises.push(writeSome(value));
  });

  $q.all(promises).then(lastTask);

  return defer;
}

在ES2017和
async/await
(请参阅下面的ES2017中的选项)之前,如果您希望等待承诺,则不能使用
.forEach()
,因为承诺没有阻塞。Javascript和承诺就是不能这样工作

  • 您可以链接多个承诺,并让承诺基础架构对它们进行排序

  • 您可以手动迭代,并仅在前一个承诺完成时推进迭代

  • 您可以使用像
    async
    Bluebird
    这样的库为您排序

  • 有很多不同的选择,但是
    .forEach()
    不能为您提供


    下面是一个使用承诺链和角度承诺进行排序的示例(假设
    对象
    是一个数组):

    使用标准ES6承诺,这将是:

    objects.reduce(function(p, val) {
        return p.then(function() {
            return doSomething(val);
        });
    }, Promise.resolve()).then(function(finalResult) {
        // done here
    }, function(err) {
        // error here
    });
    

    下面是一个手动排序的示例(假设
    对象
    是一个数组),但这不会像上面的选项那样报告完成或错误:

    function run(objects) {
        var cntr = 0;
    
        function next() {
            if (cntr < objects.length) {
                doSomething(objects[cntr++]).then(next);
            }
        }
        next();
    }
    

    代码必须包含在
    async
    函数中,然后可以使用
    wait
    告诉解释器在继续循环之前等待承诺解析。注意,虽然这似乎是“阻塞”类型的行为,但它并没有阻塞事件循环。事件循环中的其他事件仍然可以在
    等待期间处理

    是您可以使用
    angular.forEach
    来实现这一点

    下面是一个示例(假设
    对象
    是一个数组):


    下面是如何使用
    数组来实现这一点。reduce
    ,类似于@friend00的答案(假设
    对象
    是一个数组):


    最简单的方法是创建一个函数,并在解析每个承诺后手动迭代数组中的所有对象

    var delayedFORLoop = function (array) {
        var defer = $q.defer();
    
        var loop = function (count) {
            var item = array[count];
    
            // Example of a promise to wait for
            myService.DoCalculation(item).then(function (response) {
    
            }).finally(function () {
              // Resolve or continue with loop
                if (count === array.length) {
                    defer.resolve();
                } else {
                    loop(++count);
                }
            });
        }
    
        loop(0); // Start loop
        return defer.promise;
    }
    
    // To use:
    delayedFORLoop(array).then(function(response) {
        // Do something
    });
    
    我的GitHub上也提供了示例:

    这可能会对某些人有所帮助,因为我尝试了上述几种解决方案,然后提出了自己的解决方案,但实际上对我有效(其他解决方案没有)


    对我来说就是这样。我不知道这是否是一个正确的方法,但可以帮助减少线

    function myFun(){
         var deffer = $q.defer();
         angular.forEach(array,function(a,i) { 
              Service.method(a.id).then(function(res) { 
                   console.log(res); 
                   if(i == array.length-1) { 
                          deffer.resolve(res); 
                   } 
              }); 
         });
         return deffer.promise;
    }
    
    myFun().then(function(res){
         //res here
    });
    

    我使用一个简单的解决方案连接到打印机,等待承诺结束后再转到下一个打印机

    angular.forEach(object, function(data){
        yourFunction(data)
        .then(function (){
            return;
        })
    })
    

    在我看来,它可以并行运行所有操作,并使用
    q.all()
    来知道这些操作何时完成。我想OP询问了如何一次一个地对操作进行排序。你的“reduce”解决方案很优雅,但不太管用
    $q.defer().resolve()
    解析承诺,但返回未定义,因此第一个元素的
    p
    未定义。@AgDude-如果您知道建议,请建议对我的答案进行编辑。我没有跟上所有不同的专有promise库(现在有了ES6标准),因此如果这不是创建解析promise ion angularjs来启动链的正确方法,那么我不确定它应该是什么..优雅而干净的解决方案初始值
    $q.dever().resolve()
    对我不起作用(Angular 1.4.3),
    p
    在第一次调用时是
    未定义的
    。但这确实有效:
    $q(函数(解析){resolve();})
    @Artjom-在Angular 1.5.1中,表示
    .resolve()
    返回一个承诺。也许这是在1.4.3之后添加的?无论如何,您的方法也可以正常工作。此外,它还需要是
    $q.defer().resolve()
    -您在评论中的拼写不同。我认为您也可以使用
    $q.when(true)
    。您说得很对!这应该是公认的答案。您可以使用angular.forEach来实现这一点。
    objects.reduce(function(p, val) {
        // The initial promise object
        if(p.then === undefined) {
            p.resolve(); 
            p = p.promise;
        }
        return p.then(function() {
            return doSomething(val);
        });
    }, $q.defer());
    
    var delayedFORLoop = function (array) {
        var defer = $q.defer();
    
        var loop = function (count) {
            var item = array[count];
    
            // Example of a promise to wait for
            myService.DoCalculation(item).then(function (response) {
    
            }).finally(function () {
              // Resolve or continue with loop
                if (count === array.length) {
                    defer.resolve();
                } else {
                    loop(++count);
                }
            });
        }
    
        loop(0); // Start loop
        return defer.promise;
    }
    
    // To use:
    delayedFORLoop(array).then(function(response) {
        // Do something
    });
    
      var sequence;
      objects.forEach(function(item) {
         if(sequence === undefined){
              sequence = doSomethingThatReturnsAPromise(item)
              }else{
              sequence = sequence.then(function(){
                   return doSomethingThatReturnsAPromise(item)
                         }); 
                     }
            });
    
    function myFun(){
         var deffer = $q.defer();
         angular.forEach(array,function(a,i) { 
              Service.method(a.id).then(function(res) { 
                   console.log(res); 
                   if(i == array.length-1) { 
                          deffer.resolve(res); 
                   } 
              }); 
         });
         return deffer.promise;
    }
    
    myFun().then(function(res){
         //res here
    });
    
    angular.forEach(object, function(data){
        yourFunction(data)
        .then(function (){
            return;
        })
    })