微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我的快递电话出了什么问题?我需要一个 ID 数组,但它返回一个空数组

如何解决我的快递电话出了什么问题?我需要一个 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。与其使用函数外部的 batchtradeOfferQuery 对象,这会使这变得更加不清楚,您应该将它们滚动到函数中并将其从 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?