我应该如何解决 forEach 中的承诺



我有一个函数,可以循环遍历发票,然后调用API以获取有关发票的更多详细信息。我想将发票的详细信息添加到数组中。

我下面的代码确实正确获取了发票详细信息,但我无法弄清楚如何将该发票详细信息添加到数组中,"发票"对我来说总是 []。我认为这与我需要如何解决 API 调用的承诺有关?

//some other promise
var invoiceInfo = customerBalance.Rows.Row;
var customerInvoices = {
    "customerName": headerInfo[0].value,
    "customerId": headerInfo[0].id,
    "customerPhone": "",
    "invoices": []
}
invoiceInfo.forEach(function(invoice, index) {
    //only add overdue invoices
    if (invoice.ColData[3].value <= today) {
        if (invoice.ColData[1].value == "Invoice") {
            getInvoiceDetail(senderId, invoice.ColData[1].id).then(function(invoiceDetails) {
                customerInvoices.invoices.push(invoiceDetails);
                resolve(customerInvoices); //how should i resolve this?
            }, function(err) {
                console.log(err);
                reject(err);
            });
        }
    }                                        
});
console.log("CUSTOMER INVOICES: " + JSON.stringify(customerInvoices, null, 4));
overdueInvoices.push(customerInvoices);
//resolve some other promise

提前感谢!

如果你的getInvoiceDetail()函数返回承诺,你可以使用async/await

var invoiceInfo = customerBalance.Rows.Row;
var customerInvoices = {
    "customerName": headerInfo[0].value,
    "customerId": headerInfo[0].id,
    "customerPhone": "",
    "invoices": []
}
invoiceInfo.forEach(async (invoice, index) => {
    if (invoice.ColData[3].value <= today) {
        if (invoice.ColData[1].value == "Invoice") {
            const invoiceDetails = await getInvoiceDetail(senderId, invoice.ColData[1].id)
            customerInvoices.invoices.push(invoiceDetails);
        }
    }
});

您可以承诺用于获取数据的函数,如下所示:

const getInvoiceDetailPromisified = (senderId, id) => {
  return new Promise((resolve, reject) => {
    getInvoiceDetail(senderId, id).then(
      invoiceDetails => {
        resolve(invoiceDetails); //how should i resolve this?
      },
      error => {
        console.log(error);
        reject(error);
      },
    );
  });
};

承诺是将接收回调的函数转换为返回回调的函数的艺术

考虑到这一点,您可以浏览invoiceInfo中的所有元素,并将它们映射到此承诺,如下所示:

const customerInvoicesPromise = invoiceInfo.reduce((acc, invoice) => {
  // if its overdue append it do the accumulation as a promise
  if (invoice.ColData[3].value <= today && invoice.ColData[1].value == 'Invoice') {
    return acc.concat(getInvoiceDetailPromisified(senderId, invoice.ColData[1].id));
  }
  // else just return the transformation
  return acc;
}, []);

然后,如果您有权访问 async/await,您可以这样做

const customerInvoices = await Promise.all(customerInvoicesPromise);

或者如果没有,你可以用标准的方式解决承诺

Promise.all(customerInvoicesPromise).then(data => {
  // do something
});

Promise.all 接受一系列承诺,并在解析元素中的每个承诺时解析。好吧,它也😄返回了一个承诺

希望这有帮助!

最新更新