我的firebase函数更新文档第一次执行需要几分钟

eyh26e7m  于 2022-11-25  发布在  其他
关注(0)|答案(1)|浏览(107)

我正在开发一个在线订购食物的应用程序。作为后端服务,我使用firestore来存储数据和文件。用户可以订购菜肴,但库存是有限的。因此,每次用户订购一道菜并创建一个篮子 * a时,我更新**相应订购菜肴的库存。我使用firebase函数来执行此操作。老实说,这是我创建的第一个firebase函数。在Basket对象中,有一个带有相应数据库DishID的已订购菜肴列表。当创建了篮子时,我浏览了Dishid列表,并更新了Firestore数据库中的数量。在我的本地模拟器上,它工作得非常完美,速度非常快。但在网上,第一次更新需要几分钟。我可以处理几秒钟。即使需要几秒钟(像冷重启)也没关系。但有时可能需要3分钟,其他人可以在这段时间内点一道菜。
下面是我的代码:

//Update the dishes quantities when a basket is created
exports.updateDishesQuantity = functions.firestore.document('/Baskets/{documentId}').onCreate(async (snap, context) => {

      try{
        //Get the created basket
        const originalBasket = snap.data();

        originalBasket.OrderedDishes.forEach(async dish => {
          const doc = await db.collection('Dishes').doc(dish.DishID);
          console.log('Doc created');

          return docRef = doc.get()
          .then((result) =>{
            console.log('DocRef created');
            if(result.exists){
              console.log('Result exists');
              const dishAvailableOnDataBase = result.data().Available;
              console.log('Data created');
              const newQuantity = { Available: Math.max(dishAvailableOnDataBase - dish.Quantity, 0)};
              console.log('Online doc updated');
              return result.ref.set(newQuantity, { merge: true });
            }else{
              console.log("doc doesnt exist");
            }
            
          })
          .catch(error =>{
            console.log(error);
            return null;
          });       
        });

      }catch(error){
        console.log(error);
      }

});

我有几个日志输出来调试服务器上的输出。它是doc.get()函数,它需要2分钟来执行,正如你在下面的日志中看到的:Firebase logger
谢谢你的帮助,

mbyulnm0

mbyulnm01#

您不应该在forEach()循环中使用async/await,请参阅“JavaScript: async/await with forEach()“和“Using async/await with a forEach loop“。
由于您的代码以并行方式执行对异步Firebase get()set()方法的不同数量的调用,因此您应该使用Promise.all()
您应该沿着以下思路重构您的云函数:

//Update the dishes quantities when a basket is created
exports.updateDishesQuantity = functions.firestore.document('/Baskets/{documentId}').onCreate(async (snap, context) => {

    try {
        //Get the created basket
        const originalBasket = snap.data();

        const promises = [];
        originalBasket.OrderedDishes.forEach(dish => {
            promises.push(db.collection('Dishes').doc(dish.DishID).get());
        });
        const docSnapshotsArray = await Promise.all(promises);

        const promises1 = [];
        docSnapshotsArray.forEach(snap => {
            if (result.exists) {
                const dishAvailableOnDataBase = result.data().Available;
                const newQuantity = { Available: Math.max(dishAvailableOnDataBase - dish.Quantity, 0) };
                promises1.push(result.ref.set(newQuantity, { merge: true }));
            }
        })

        return Promise.all(promises1)

    } catch (error) {
        console.log(error);
        return null;
    }

});

请注意,您可以使用map()方法来代替循环和调用push(),以获得更简洁的代码。然而,对于SO答案,我喜欢创建一个空数组,用forEach()循环填充它并将其传递给Promise.all()所带来的清晰度...
另请注意,由于您要更新购物篮中的数量,因此可能需要使用Transaction

相关问题