【问题标题】:Promise.all does not wait for all the promise to finish firestore data readPromise.all 不会等待所有的 Promise 完成 Firestore 数据读取
【发布时间】:2018-09-14 21:24:03
【问题描述】:

我有以下数据结构将添加到 Firestore collectiondocument

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

所以我将拥有产品对象数组,每个产品将拥有插件对象数组。

我试图在将价格保存为文档之前从 db 中检索价格,因此我为该特定表编写了 .onCreate 函数。要检索product 级别和addon 级别的价格,我有以下两个承诺:

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

然后我确实有

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

但这不会等待任何承诺解决。当我记录结果时,我得到如下。

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

我的问题是,为什么不等待所有的承诺解决?我从firestore获取query返回数据的方式有什么问题吗?

【问题讨论】:

  • productPromises 和 addonPromise 是 Promise 数组,因此您传递给 Promise.all 的数组是数组数组,而不是 Promise 数组 - 试试 Promise.all([...productPromises, ...addonPromise]).then
  • 既然已经有一个从 get().then().catch() 返回的 Promise 对象,为什么还要创建一个新的 Promise 对象?
  • @DougStevenson 我没听明白。
  • @JaromandaX 正在尝试。请稍等。
  • @GuruprasadRao - 他的意思是Avoid the promise constructor anti-pattern

标签: javascript promise google-cloud-functions google-cloud-firestore


【解决方案1】:

map 构建一个返回值数组,所以你可以写:

  const productPromises = _.map(products, product => db.doc(`product/${product.productId}`).get()
       .then(docData => ({
            productId: product.productId,
            halfkgprice: docData.data().halfkgprice,
            price: docData.data().price
        })
  );

【讨论】:

  • 这看起来还是很简单的。你能否让我知道这是否比目前的方法更好,如果是的话如何?我只是了解promises 的初学者,所以我想知道.. :)
  • 查看developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 以了解地图的工作原理。你如何使用它就像一个 .forEach() 调用。但在它下面仍然创建一个 [undefined, undefined, undefined...] 数组(因为您没有在 map 函数中返回任何内容),然后您将其丢弃。一旦您按预期使用 map(),它实际上使事情变得更简单。 :)
【解决方案2】:

productPromisesaddonPromise 是 promise 数组,因此您传递给 Promise.all 的数组是数组数组,而不是 promise 数组 - 试试

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

另外,避免 Promise 构造函数反模式

_.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
            });
        })
    );
});

【讨论】:

  • 很棒的兄弟。太感谢了。它帮助很大.. :)
【解决方案3】:

您需要连接 2 个数组以使其按预期工作

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 2020-06-23
    • 2017-09-10
    相关资源
    最近更新 更多