【问题标题】:Loop wait till all promises are resolved before the next iteration [duplicate]循环等待,直到在下一次迭代之前解决所有承诺 [重复]
【发布时间】:2017-06-01 08:14:54
【问题描述】:

这是我对 AngularJS 的要求:

 for (var i = 0, len = self.Scope.data.length; i < len; i++) 
{

         var data = self.Scope.data[i];
         var self = this;
//First asynchronous function
self.EcritureService.createNewData(data).then(() => {
         })                                                     
//Second asynchronous function
self.OperationService.getOperation(data.idOperation).then((operation) => {

         })   
//Third asynchronous function
self.AccountService.getAccount(data.codeCompte).then((compte) => {
               currentAccount = compte;
               currentAccount.montant = currentAccount.montant+data.montant;
         })   
//Fourth one relies on the third result, So it must be executed sequentially
self.AccountService.updateAccount(currentAccount).then(() => {
         })                    
}
// After all fetch loop's promises are resolved I want to execute some instructions here for to update the operation retrieved in the second function.

我希望这个循环迭代器等到所有承诺都解决后再继续下一步,而不是确保所有工作都已完成,移至位于循环块之外的最后一个功能

【问题讨论】:

  • 你能修正你的缩进吗?
  • JavaScript 是单线程的。 for 循环将在解决任何承诺之前完成。不能让循环等待。
  • 您可以将逻辑编写为同步的,将其放入函数中,然后通过同步执行器nsynjs 执行该函数。请参阅此处类似示例中的函数“process()”:github.com/amaksr/nsynjs/blob/master/examples/…

标签: javascript angularjs promise angular-promise


【解决方案1】:

创建 Promise 数组并在所有 Promise 解决后使用 $q.all(promise_array) 运行

// map array of `$q.all()` promises
let promises = self.Scope.data.map((data) => {
  //First asynchronous function
  let promise_1 = self.EcritureService.createNewData(data).then(() => {})
  //Second asynchronous function
  let promise_2 = self.OperationService.getOperation(data.idOperation).then((operation) => {

  })
  //Third asynchronous function
  let promise_3 = self.AccountService.getAccount(data.codeCompte).then((compte) => {
    currentAccount = compte;
    currentAccount.montant = currentAccount.montant + data.montant;
    return currentAccount;
  }).then((currentAccount) => {
    //return promise of 4th inside `then()` of third
    return self.AccountService.updateAccount(currentAccount).then(() => {});
  });

  // this `$q.all()` resolves when this mapped instance of above all resolve
  return $q.all([promise_1, promise_2, promise_3]);

});

// resolves when all the loop instances of `$q.all()` resolve
$q.all(promises).then(()=>{
  // run completion code here
}).catch(err=>{
  console.log('Something failed in promise chain')
})

【讨论】:

  • 哈 - 太棒了 :) $q.all 的数组然后是 $q.all'ed - 喜欢它:) 比递归循环好得多!
【解决方案2】:

首先,我会说您可能不希望这些服务成为承诺,因为您正试图绕过它们的“承诺”。所以最简单的解决方案是重写服务以正常返回而不是通过承诺。

但要回答你的问题。第二部分首先 - 将第 4 个承诺链接到第 3 个承诺的最简单方法就是将其放在第 3 个 .then 中,如下所示:

//Third asynchronous function 
self.AccountService.getAccount(data.codeCompte).then((compte) => {
           currentAccount = compte;
           currentAccount.montant = currentAccount.montant+data.montant; 
           //Fourth one relies on the third result, So it must be executed sequentially
           self.AccountService.updateAccount(currentAccount).then(() => {
     })  
 })

如果您将任何错误处理放入其中,那么您可能会决定将嵌套的 Promise 放入 .finally 子句中。

至于让循环等待,for 循环并不是专门为此设计的。实现这一目标的最简单方法是编写自己的循环并使用 $q.all 将 Promise 组合在一起。您需要跟踪一个循环计数器,在 $q.all 的 .then 中递增该计数器,并使用一个递归函数,该函数在完成所需数量的循环时中断。

【讨论】:

    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2020-06-20
    • 2020-11-18
    • 2014-03-12
    • 2018-03-22
    相关资源
    最近更新 更多