繁体   English   中英

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

[英]What is going wrong with my express call? I need an array of ID's but its returning an empty array

我猜这个问题是因为我不知道如何有效地使用异步等待。 我仍然不明白,我多年来一直在努力理解。 叹。

无论如何,这是我的 function:

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他们的评论中指出的那样,在您的getIdsToDecline function 中存在错误链接的Promise问题。

目前 function 初始化一个名为tempArray的数组,开始执行交易报价查询,然后返回该数组(目前仍为空),因为查询尚未完成。

虽然您可以在tradeOfferQuery.get()之前加入await ,但这并不能解决您的问题,因为它只会等待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, { itemID }) => set.add(itemID), 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。 不要使用 function 之外的batchtradeOfferQuery对象,这会使这变得更加不清楚,您应该将它们滚动到 function 中并将其拉出快速处理程序。 我还将把它重命名为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 for HTTP 200 OK的错误使用,并使用json()而不是send() 你现在得到:

app.post("/declineTrades", async (request, 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
    }
  }
});

注意:即使进行了所有这些更改,您仍然缺少任何形式的身份验证。 Consider swapping the HTTPS Event Function out for a Callable Function where this is handled for you but requires using a Firebase Client SDK.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM