首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在javascript中迭代数组,并在循环块中包含promises,并等待所有promises完成后再继续

如何在javascript中迭代数组,并在循环块中包含promises,并等待所有promises完成后再继续
EN

Stack Overflow用户
提问于 2018-10-03 06:34:16
回答 1查看 221关注 0票数 1

我需要使用一些值迭代javascript中的一个数组,这些值将用于调用一个返回promise的异步函数。在没有完成所有承诺的情况下,我无法继续下一个代码部分。

在下面的示例中,函数"processInvoices“必须解析一个promise,直到其中的所有promise都完成(假设"confirmInvoice”是一个具有不同响应时间的异步函数):

代码语言:javascript
复制
processInvoices(invoices)
{
  return new promise((resolve,reject)=>
    {
        invoices.forEach(number=> 
            {
            
                confirmInvoice(number)
                    .then(result=>{
                              if (!result)
                                {reject('Error confirming the invoice');}
                    });
            });
        resolve(true);  // Resolving here doesn´t mean that all promises were completed!

    });
}

init()  // triggered at load..
{
    let invoices = [2,4,8,16,31];
    processInvoices(invoices)
        .then(result=>
            { 
                if (result) // It´s probable that the following message isn´t accurate:
                    console.log('All invoices were processed');
            }).catch(reason=>{console.error(reason)});

}

使用上面的代码,我不能确定"console.log (或任何例程)“是否会在所有承诺完成后立即执行。

更新 Promise.all(iterable)解决了这个问题:

代码语言:javascript
复制
processInvoices(invoices)
{
  return new promise((resolve,reject)=>
    {
        var promisesArray = []; // store all promises here
        invoices.forEach(number=> 
            {
            
                promisesArray.push(confirmInvoice(number));
                    
            });
       Promise.all(promisesArray).then (results=>{
        // validate all results and reject if necessary...
        if (validateResults(results)) {
        // if all ok
            resolve('All invoices were processed successfully');
          }
        else {
          reject('Error processing one or more invoices'); // just for demo purposes
         }
        });                 

    });
}

init()  // triggered at load..
{
    let invoices = [2,4,8,16,31];
    processInvoices(invoices)
        .then(result=>
            {                   
            console.log(result);
            }).catch(reason=>{console.error(reason)});

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-03 06:43:20

forEach同步运行。如果您希望在整个processInvoices解析之前等待所有承诺的解析,则应该改用Promise.all;将每个发票号map到一个Promise,并对生成的承诺数组调用Promise.all。另外,您的

代码语言:javascript
复制
if (!result) {resolve(false);}

这听起来像是在尝试处理错误,以防没有结果-在这种情况下,您应该拒绝Promise而不是调用resolve。理想情况下,失败的confirmInvoice调用将导致被拒绝的Promise,但是如果这不是您可以修复的,那么如果result是False值,那么就抛出一个错误,这样您就可以在initcatch中处理它。例如:

代码语言:javascript
复制
function processInvoices(invoices) {
  return Promise.all(
    invoices.map(number => (
      confirmInvoice(number)
        .then(result => {
          // This will result in the `Promise.all` rejecting:
          if (!result) throw new Error('Failed to confirm invoice ' + number);
        })
    ))
  );
}
function init() {
  const invoices = [2, 4, 8, 16, 31];
  processInvoices(invoices)
    .then(result => {
        console.log('All invoices were processed');
    })
    .catch((err) => {
      console.log('err: ' + err);
    });
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52617354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档