如何循环firebase的异步查询代码?

时间:2019-04-03 11:55:11

标签: javascript firebase asynchronous promise google-cloud-firestore

我正在尝试循环并从Firestore获取不同的文档。如下面的代码所示,“文档ID”由名为“购物车”的数组提供。

我尝试过的编程逻辑是这样的,每次迭代中的while循环都从firestore获取文档,在第一个“ then”部分中,它将保存刚获取的数据,在第二个“ then”中,将增量“ i” ',然后执行下一个循环。

问题是while循环不等待获取请求完成。它只是不断循环和崩溃。

即使我设法以某种方式正确完成了循环部分,事情也是如此。我将如何管理程序的整体执行流程,以便仅在完成循环部分后才执行其他代码,因为下面的代码使用了循环部分更新的购物车数组。

let i = 0
while (i < cart.length) {
    let element = cart[i]
    db.collection(`products`).doc(element.productID).get().then((doc1) => {
        element.mrp = doc1.data().mrp
        element.ourPrice = doc1.data().ourPrice
        return console.log('added price details')
    }).then(() => {
        i++;
        return console.log(i)
    }).catch((error) => {
        // Re-throwing the error as an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('unknown', error.message, error);
    });
}
return db.collection(`Users`).doc(`${uid}`).update({
    orderHistory: admin.firestore.FieldValue.arrayUnion({
        cart,
        status: 'Placed',
        orderPlacedTimestamp: timestamp,
        outForDeliveryTimestamp: '',
        deliveredTimestamp: ''
    })
}).then(() => {
    console.log("Order Placed Successfully");
})

2 个答案:

答案 0 :(得分:1)

您的问题不是关于firebase,您是在询问异步循环。您可以看到一些promises示例hereasync/await here

您可以在promise中使用reduce。 请注意,所有的Promise都是同时创建的,但是对服务器的调用是一个接一个地完成的。

cart.reduce(
  (promise, element) =>
    promise.then(() => {
      return db.collection(`products`)
        .doc(element.productID)
        .get()
        .then(doc1 => {
          element.mrp = doc1.data().mrp;
          element.ourPrice = doc1.data().ourPrice;
        });
    }),
  Promise.resolve()
);

如果可以,请改用async/await。在这里,所有的诺言都是一个接一个地创建的。

async function fetchCart() {
  for (const element of cart) {
    const doc1 = await db.collection(`products`).doc(element.productID);
    element.mrp = doc1.data().mrp;
    element.ourPrice = doc1.data().ourPrice;
    console.log('added price details');
  }
}

答案 1 :(得分:0)

对Cloud Firestore的每次调用都是异步发生的。因此,您的while循环会触发多个此类请求,但不会等待它们完成。

如果您的代码需要所有结果,则需要使用Promises来确保流程。您已经在while循环中使用promise来获取doc1.data().mrp。如果cart是一个数组,则可以执行以下操作来收集有关何时加载数据的所有承诺:

var promises = cart.map(function(element) {
   return db.collection(`products`).doc(element.productID).get().then((doc1) => {
        return doc1.data();
    });
});

现在您可以使用以下方法等待所有数据:

Promise.all(promises).then(function(datas) {
  datas.forEach(function(data) {
    console.log(data.mrp, data.ourPrice);
  });
});

如果您使用的是现代环境,则可以使用async / await来提取then

datas = away Promise.all(promises);
datas.forEach(function(data) {
  console.log(data.mrp, data.ourPrice);
});