处理云函数中的嵌套承诺

时间:2019-12-05 01:07:37

标签: node.js typescript promise async-await google-cloud-firestore

我是使用async-await编写打字稿的新手,但是我检索了所有折扣,检查是否已激活或已过期,如果已过期,则获取所有折扣产品,然后在响应上打印其ID,这是我无法处理嵌套承诺的问题,获取打折产品的ID以作为响应显示

exports.terminateDiscount = functions.https.onRequest(async (req, res) => {
    try {
        const discountSnapshots = await admin.firestore().collection("Discounts").get();
        const promises = [];
        const today = Date.now();
        discountSnapshots.forEach(async discountSnapshot => {
            const startDate = +discountSnapshot.data().startDate.toMillis();
            const endDate = discountSnapshot.data().endDate;
            if (today > startDate && endDate !== null && today > endDate.toMillis()) { // discount expired
                promises.push(discountSnapshot.id); // print discount id only
                const discountProducts=await admin.firestore().collection("Products").where("discountId", "==", discountSnapshot.id).get();
                discountProducts.forEach(product => {
                     promises.push(product.id); // products id's not added in promises :(
                });
            }
        });
        res.send(await Promise.all(promises));
    } catch (error) {
    }
});

1 个答案:

答案 0 :(得分:1)

很难将async/await.forEach一起使用。简单来说,.forEach会针对数组的每个项目调用一个回调,它始终是一个sync进程。这意味着,您将永远不会等到const discountProducts = await admin.firestore()...完成后,在调用discountSnapshots.forEach...之后立即返回。

Promise.all在给它一个promises数组时工作得很好,在您的代码中,您将一个字符串数组(我认为discountSnapshot.id是一个字符串)传递给Promise.all,在这种情况下它将返回“原始”输入-字符串数组。

在这种情况下,我建议使用Array.map.map函数将返回一个数组,我们使它返回一个promises数组,然后等到所有的promises完成。

exports.terminateDiscount = functions.https.onRequest(async (req, res) => {
  try {
    const discountSnapshots = await admin.firestore().collection("Discounts").get();
    const today = Date.now();

    const ids = []; // to store discount id or products id or both ????

    const promises = discountSnapshots.docs.map(async (discountSnapshot) => {
      const startDate = +discountSnapshot.data().startDate.toMillis();
      const endDate = discountSnapshot.data().endDate;
      if (today > startDate && endDate !== null && today > endDate.toMillis()) { // discount expired
        ids.push(discountSnapshot.id); // print discount id only ???
        const discountProducts = await admin.firestore().collection("Products").where("discountId", "==", discountSnapshot.id).get();
        discountProducts.forEach(product => {
          ids.push(product.id); // products id's ??? "print discount id only"
        });
      }
    });
    await Promise.all(promises); // wait until we fill the ids array, the ids has been filled.

    res.send(ids);
  } catch (error) {
  }
});