如何解决我的快递电话出了什么问题?我需要一个 ID 数组,但它返回一个空数组
我猜这个问题是因为我不知道如何有效地使用 async await。我仍然不明白,我一直试图理解多年。叹气。
无论如何,这是我的功能:
app.post("/declineTrades",async (request,response) => {
//---------------------------------------------
const batch = db.batch();
const listingID = request.body.listingID;
const tradeofferQuery = db
//---------------------------------------------
//Get Trade offers that contain the item that just sold
//(therefore it cannot be Traded anymore,I need to cancel all existing Trade offers that contain the item because this item isn't available anymore)
//---------------------------------------------
.collection("tradeoffers")
.where("status","==","pending")
.where("itemIds","array-contains",listingID);
//---------------------------------------------
//Function that gets all Trade offers that contain the ID of the item.
async function getIdsToDecline() {
let tempArray = [];
tradeofferQuery.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
//For each Trade offer found
let offerRef = db.collection("tradeoffers").doc(doc.id);
//Change the status to declined
batch.update(offerRef,{ status: "declined" });
//Get the data from the Trade offer because I want to send an email
//to the who just got their Trade offer declined.
const offerGet = offerRef.get().then((offer) => {
const offerData = offer.data();
//Check the items that the receiving person had in this Trade offer
const receiverItemIds = Array.from(
offerData.receiversItems
.reduce((set,{ itemID }) => set.add(itemID),new Set())
.values()
);
//if the receiver item id's array includes this item that just sold,I kNow that
//I can get the sender ID (users can be sender or receiver,so i need to check which person is which)
if (receiverItemIds.includes(listingID)) {
tempArray.push(offerData.senderID);
}
});
});
});
//With the ID's Now pushed,return the tempArray
return tempArray;
}
//---------------------------------------------
//Call the above function to get the ID's of people that got declined
//due to the item no longer being available
const peopletoDeclineArray = await getIdsToDecline();
//Update the Trade offer objects to declined
const result = await batch.commit();
//END
response.status(201).send({
success: true,result: result,idArray: peopletoDeclineArray,});
});
我猜我的 return tempArray
放错了地方?但我试过把它放在其他地方,它仍然返回一个空数组。我的逻辑在这里正确吗?我需要在 batch.commit
发生之前和发送响应之前运行 forEach 循环并添加到数组中。
TIA 伙计们!
解决方法
正如 @jabaa 中的 their comment 所指出的,您的 Promise
函数中存在错误链接的 getIdsToDecline
问题。
当前该函数初始化一个名为 tempArray
的数组,开始执行交易报价查询,然后返回该数组(当前仍为空),因为查询尚未完成。
虽然您可以在 await
之前输入 tradeOfferQuery.get()
,但这并不能解决您的问题,因为它只会等待 tradeOfferQuery
执行和批次填充条目,同时仍未等待任何 offerRef.get()
调用完成以填充 tempArray
。
要解决此问题,我们需要确保所有 offerRef.get()
调用先完成。要获取所有这些文档,您可以使用以下代码获取每个文档,等待所有文档完成,然后提取快照:
const itemsToFetch = [ /* ... */ ];
const getAllItemsPromise = Promise.all(
itemsToFetch.map(item => item.get())
);
const fetchedItemSnapshots = await getAllItemsPromise;
对于基于查询的文档,您可以将其调整为:
const querySnapshot = /* ... */;
const getSenderDocPromises = [];
querySnapshot.forEach((doc) => {
const senderID = doc.get("senderID");
const senderRef = db.collection("users").doc(senderID);
getSenderDocPromises.push(senderRef.get());
}
const getAllSenderDocPromise = Promise.all(getSenderDocPromises);
const fetchedSenderDataSnapshots = await getAllSenderDocPromise;
然而,这两种方法都不是必需的,因为您使用这些 offerRef.get()
调用请求的文档已经在您的查询中返回,因此我们甚至不需要在这里使用 get()
!
(doc) => {
let offerRef = db.collection("tradeOffers").doc(doc.id);
//Change the status to declined
batch.update(offerRef,{ status: "declined" });
//Get the data from the trade offer because I want to send an email
//to the who just got their trade offer declined.
const offerGet = offerRef.get().then((offer) => {
const offerData = offer.data();
//Check the items that the receiving person had in this trade offer
const receiverItemIds = Array.from(
offerData.receiversItems
.reduce((set,{ itemID }) => set.add(itemID),new Set())
.values()
);
//if the receiver item id's array includes this item that just sold,I know that
//I can get the sender ID (users can be sender or receiver,so i need to check which person is which)
if (receiverItemIds.includes(listingID)) {
tempArray.push(offerData.senderID);
}
});
}
可以只替换
(doc) => {
// Change the status to declined
batch.update(doc.ref,{ status: "declined" });
// Fetch the IDs of items that the receiving person had in this trade offer
const receiverItemIds = Array.from(
doc.get("receiversItems") // <-- this is the efficient form of doc.data().receiversItems
.reduce((set,new Set())
.values()
);
// If the received item IDs includes the listed item,add the
// sender's ID to the array
if (receiverItemIds.includes(listingID)) {
tempArray.push(doc.get("senderID"));
}
}
可以简化为
(doc) => {
//Change the status to declined
batch.update(doc.ref,{ status: "declined" });
// Check if any items that the receiving person had in this trade offer
// include the listing ID.
const receiversItemsHasListingID = doc.get("receiversItems")
.some(item => item.itemID === listingID);
// If the listing ID was found,add the sender's ID to the array
if (receiversItemsHasListingID) {
tempArray.push(doc.get("senderID"));
}
}
基于此,getIdsToDecline
实际上会排队拒绝无效交易并返回受影响的发件人的 ID。与其使用函数外部的 batch
和 tradeOfferQuery
对象,这会使这变得更加不清楚,您应该将它们滚动到函数中并将其从 express 处理程序中拉出。我还将其重命名为 declineInvalidTradesAndReturnAffectedSenders
。
async function declineInvalidTradesAndReturnAffectedSenders(listingID) {
const tradeOfferQuery = db
.collection("tradeOffers")
.where("status","==","pending")
.where("itemIds","array-contains",listingID);
const batch = db.batch();
const affectedSenderIDs = [];
const querySnapshot = await tradeOfferQuery.get();
querySnapshot.forEach((offerDoc) => {
batch.update(offerDoc.ref,{ status: "declined" });
const receiversItemsHasListingID = offerDoc.get("receiversItems")
.some(item => item.itemID === listingID);
if (receiversItemsHasListingID) {
affectedSenderIDs.push(offerDoc.get("senderID"));
}
}
await batch.commit(); // generally,the return value of this isn't useful
return affectedSenderIDs;
}
这会将您的路由处理程序更改为:
app.post("/declineTrades",async (request,response) => {
const listingID = request.body.listingID;
const peopleToDeclineArray = await declineInvalidTradesAndReturnAffectedSenders(listingID);
response.status(201).send({
success: true,result: result,idArray: peopleToDeclineArray,});
});
然后添加适当的错误处理,将 HTTP 201 Created
的错误使用替换为 HTTP 200 OK
,并使用 json()
代替 send()
;你现在得到:
app.post("/declineTrades",response) => {
try {
const listingID = request.body.listingID;
const affectedSenderIDs = await declineInvalidTradesAndReturnAffectedSenders(listingID);
response.status(200).json({
success: true,idArray: affectedSenderIDs,// consider renaming to affectedSenderIDs
});
} catch (error) {
console.error(`Failed to decline invalid trades for listing ${listingID}`,error);
if (!response.headersSent) {
response.status(500).json({
success: false,errorCode: error.code || "unknown"
});
} else {
response.end(); // forcefully end corrupt response
}
}
});
注意:即使进行了所有这些更改,您仍然缺少任何形式的身份验证。考虑将 HTTPS 事件函数替换为 Callable Function,其中会为您处理但需要使用 Firebase 客户端 SDK。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。