【问题标题】:Handle nested promises in cloud functions处理云函数中的嵌套承诺
【发布时间】:2020-03-29 21:22:35
【问题描述】:

我是使用 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) {
    }
});

【问题讨论】:

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


    【解决方案1】:

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

    Promise.all 如果你给它一个 promises 数组就可以正常工作,在你的代码中,你将一个字符串数组(我认为discountSnapshot.id 是一个字符串)传递给Promise.all,在这种情况下它将返回“原始”输入 - 字符串数组。

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

    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) {
      }
    });
    

    【讨论】:

    • 给了我这个错误,“QuerySnapshot”类型上不存在属性“map”。
    • @AhmedAbdElfattah 我更新了我的答案。 discountSnapshots.docs.map 而不是 discountSnapshots.map
    • 当 .map() 回调中没有 return 语句时,这将如何工作?为什么await Promise.all(ids) ids 是一个值数组,而不是 Promises?
    • @Roamer-1888 如果地图回调中不返回任何内容,则默认返回undefined,在这种情况下,返回值的类型为Promise<void>。是的,你是对的,我们只需要res.send(ids);,谢谢你的指点。
    • 如果promises 是一个未定义数组,那么为什么await(Promise.all(promises))
    猜你喜欢
    • 1970-01-01
    • 2019-02-24
    • 2018-12-03
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    相关资源
    最近更新 更多