2

I have below data structure that will be added to the firestore collection as document

{
    ".......": "......." //few more properties
    "productInfo": {
        "0": {
            "code": "SC05",
            "price": 400,
            "productId": "asUsd1HPEPOo2itiKxdash",
            ".......": "......." //few more properties
            "addOns": [{
                    "aid": "4casedasgdfdgfas",
                    "price": "50",
                    "......": "....." //few more properties
            }]
        }
    }
}

So I will be having array of products object and each product will have array of addon object.

I am trying to retrieve price from db before saving it as document and hence I've written .onCreate function for that particular table. To retrieve price on the product level and addon level, I am having 2 promises as below:

const productPromises = [];
_.map(products, (product) => {
    productPromises.push(new Promise((resolve, reject) => {
        db.doc(`product/${product.productId}`).get().then(docData => {
            return resolve({
                productId: product.productId,
                halfkgprice: docData.data().halfkgprice,
                price: docData.data().price
            });
        }).catch(reason => {
            return reject(reason);
        });
    }));
});

const addonPromise = [];
_.map(products, (product) => {
    addonPromise.push(new Promise((resolve, reject) => {
        if (product.addOns !== undefined && product.addOns !== null) {
            return _.map(product.addOns, (addon) => {
                return db.doc(`addons/${addon.aid}`).get().then((addonData) => {
                    return resolve({
                        price: addonData.data().price
                     });
                }).catch(reason => {
                    return reject(reason);
                })
            });
         } else {
            return resolve();
        }
     }));
 });

and then I do have

Promise.all([productPromises, addonPromise]).then(result => {
      //do something with result
});

But this will not wait any of the promise to resolve. When I log the result I get as below.

console.log(result) will show [ [ Promise { <pending> } ], [ Promise { <pending> } ] ] and doesn't wait for them to resolve

My question is, why is not waiting for all the promises to resolve? Is there any problem with the way I am returning data from firestore get query?

Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200

3 Answers3

3

productPromises and addonPromise are arrays of promises, so the array you pass to Promise.all is an array of arrays, not an array of promises - try

Promise.all([...productPromises, ...addonPromise]).then

Also, avoid the Promise constructor anti-pattern

_.map(products, (product) => {
    productPromises.push(
        db.doc(`product/${product.productId}`).get().then(docData => {
            return ({
                productId: product.productId,
                halfkgprice: docData.data().halfkgprice,
                price: docData.data().price
            });
        })
    );
});
Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
2

You need to concat 2 arrays to make it work as expected

Promise.all(productPromises.concat(addonPromise)).then(result => {
      //do something with result
});
Denis Rybalka
  • 1,821
  • 3
  • 18
  • 28
0

map builds an array of returned values, so you can just write:

  const productPromises = _.map(products, product => db.doc(`product/${product.productId}`).get()
       .then(docData => ({
            productId: product.productId,
            halfkgprice: docData.data().halfkgprice,
            price: docData.data().price
        })
  );
smokku
  • 1,256
  • 13
  • 22
  • Well this looks still easy. Could you please let me know if this is better than current approach and if yes how? I am just beginner in understanding `promises` so I would like to know.. :) – Guruprasad J Rao Apr 05 '18 at 07:44
  • 1
    Take a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map to understand how map works. How you are using it is like a .forEach() call. But underneath it is still creating an array of [undefined, undefined, undefined...] (because you are not returning anything in the map function), which you then discard. Once you use map() as intended, it actually makes things simpler. :) – smokku Apr 06 '18 at 13:33