我应该如何在forEach中兑现承诺?

时间:2019-07-26 05:25:53

标签: javascript node.js promise

我有一个遍历发票的功能,然后调用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

谢谢!

2 个答案:

答案 0 :(得分:0)

如果您的getInvoiceDetail()函数返回了Promise,则可以使用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);
        }
    }
});

答案 1 :(得分:0)

您可以将获取数据的功能分散化,如下所示:

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;
}, []);

然后,如果您有权访问异步/等待,则可以

const customerInvoices = await Promise.all(customerInvoicesPromise);

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

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

Promise.all接受一个promise数组,当元素中的每个promise被解析时,它就会被解析。好吧,它也返回了Promise?

希望这会有所帮助!