我正在开发一个在线订购食物的应用程序。作为后端服务,我使用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
谢谢你的帮助,
1条答案
按热度按时间mbyulnm01#
您不应该在
forEach()
循环中使用async/await,请参阅“JavaScript: async/await with forEach()“和“Using async/await with a forEach loop“。由于您的代码以并行方式执行对异步Firebase
get()
和set()
方法的不同数量的调用,因此您应该使用Promise.all()
。您应该沿着以下思路重构您的云函数:
请注意,您可以使用
map()
方法来代替循环和调用push()
,以获得更简洁的代码。然而,对于SO答案,我喜欢创建一个空数组,用forEach()
循环填充它并将其传递给Promise.all()
所带来的清晰度...另请注意,由于您要更新购物篮中的数量,因此可能需要使用Transaction。