简体   繁体   中英

Handle nested promises in cloud functions

I'm new in writing typescript with async-await but I retrieved all discounts, check if active or expired, if expired get all discount products then print its id's on the response, the problem I can't handle nested promises and get ids of discounted products to display in response

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

It's so hard to use async/await with .forEach . In simple, .forEach calls a callback with each item of array, and it always is a sync process. This mean, you will never wait until const discountProducts = await admin.firestore()... finish, you return immediate after call discountSnapshots.forEach... .

Promise.all just working fine if you give it a promises array, in your code, you pass a strings arrays (I think discountSnapshot.id is a string) to Promise.all , in this case it will return "original" input - strings array.

I suggest use Array.map in this case, .map function returns a array, we make it to return a promises array, then just wait until all of promises finish.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM