【问题标题】:How i can avoid the loop on my querysnapshot.foreach?如何避免我的 querysnapshot.foreach 上的循环?
【发布时间】:2021-04-14 12:39:20
【问题描述】:

我的用户有 2 个团队:

  • 舞蹈
  • 柔道

在我的子集 "membersList" 中,Danse 团队有 1 个好友请求,而柔道则没有。

所以我想我的屏幕上只有一个请求。但是当我有 2 个或更多团队时,while 会继续循环,并且请求会显示团队的数量。

我认为问题出在我的 querySnaphost.forEach 上,但在我的控制台上,他返回给我的文档不是空的(所以团队 danse )和另一个找不到文档的文档。

let fetch = async () => {
    firestore()
      .collection("Teams")
      .where("uid", "==", await AsyncStorage.getItem("userID"))
      .get()
      .then((querySnapshot) => {
        if (querySnapshot.empty) {
          console.log("no documents found");
        } else {
          querySnapshot.forEach((doc) => {
            let Teams = doc._data;
            console.log(Teams);
            updateActivity((arr) => [...arr, Teams]);
            console.log(Activity);

            doc.ref
              .collection("membersList")
              .where("statut", "==", "en attente")
              .get()
              .then((querySnapshot) => {
                if (querySnapshot.empty) {
                  console.log("no documents found cc");
                } else {
                  querySnapshot.forEach((doc) => {
                    let members = doc._data;
                    console.log("aa", members);
                    updateMembersList((arr) => [...arr, members]);
                    console.log("cc", MembersList);
                  });
                }
              });
          });
        }
      });
  };
  useEffect(() => {
    fetch();
  }, []);

以下是调用fetch() 时记录的内容:

{"Activity": "Danse", "Adress": "Plage", "City": "Nice", "Owner": true, "members": "3", "text": "bouh", "tokenTeam": "n5ounxsf2bq", "uid": "PTbEn2fba0QudXI8JE8RioQ9of53"}
[]
no documents found cc

【问题讨论】:

  • MembersList 是否意味着包含特定用户的所有待处理好友请求的列表?同样,Activity 是否意味着包含用户拥有的每个 Team 的数组?
  • 是的,Memberslist 基本上是团队的子集合,每个团队都有自己的 memberslist !当状态“待定”时需要出现

标签: javascript firebase google-cloud-firestore


【解决方案1】:

你不应该将你的函数命名为fetch,因为这是一个reserved global function,你应该像undefined一样对待它——不要给它分配任何东西。我还建议在适用的情况下使用const 而不是let

注意:此答案使用this answer 中描述的相同策略。

const fetchMemberRequests = async () => {
  const userTeamsQuerySnapshot = await firestore()
    .collection("Teams")
    .where("uid", "==", await AsyncStorage.getItem("userID"))
    .get();

  if (userTeamsQuerySnapshot.empty) {
    console.log("User owns no teams.");

    // empty Activity & MembersLists
    updateActivity([]);
    updateMembersList([]);
    return;
  }
  
  // for each team, fetch the pending requests and return a { team, memberRequests } object
  const fetchMemberRequestsPromises = userTeamsQuerySnapshot.docs
    .map(async (teamDocSnapshot) => {
      const teamData = teamDocSnapshot.data();
      
      const memberRequestsQuerySnapshot = await teamDocSnapshot.ref
        .collection("membersList")
        .where("statut", "==", "en attente")
        .get();
        
      if (memberRequestsQuerySnapshot.empty) {
        console.log(`Activity ${teamData.Activity} has no pending requests.`);
        return {
          team: teamData,
          memberRequests: []
        }
      }
      
      const memberRequestsArray = memberRequestsQuerySnapshot.docs
        .map((memberRequestDocSnapshot) => memberRequestDocSnapshot.data());
        
      console.log(`Activity ${teamData.Activity} has ${memberRequestsArray.length} pending requests.`);
      return {
        team: teamData,
        memberRequests: memberRequestsArray
      }
    });
    
  const memberRequests = await Promise.all(fetchMemberRequestsPromises);
  
  // memberRequests is an array of { team: teamData, memberRequests: arrayOfMembers }
  // which could be used to show the requests in groups
  
  // these lines replicate your current code:
  const allTeams = [];
  const allMemberRequests = [];
  for (const request of memberRequests) {
    allTeams.push(request.team);
    allMemberRequests.push(...request.memberRequests); // note: spreads array
  }
  
  console.log(`User owns ${allTeams.length} teams, with a total of ${allMemberRequests.length} pending requests.`);
  
  // replace Activity and MembersList rather than append to them
  updateActivity(allTeams);
  updateMembersList(allMemberRequests);
}

【讨论】:

  • 除了await.map() 中不起作用:/
  • @JeremyThille 此代码按预期运行。在这段代码中,我将async 函数传递给map,其中await 是该函数的一部分。通过使用这个async 函数,map 将返回类型Promise<ResultType>[] 而不是常规类型ResultType[]。仅仅拥有一个 Promise 数组本身并不会做任何有趣的事情,但是该数组可以传递给 Promise.allPromise.allSettledPromise.anyPromise.race,然后它可以与 await 一起使用。在上面的代码中,Promise 数组被传递给了Promise.all
  • 以这种方式使用 await 允许并行运行所有异步调用,而在 for 循环中使用 await 会强制调用是顺序的。
  • 我的错,我读得太快了。我错过了Promise.all 部分。你今天纠正了我两次,谢谢:)
【解决方案2】:

您正在循环内重复使用循环中的变量(querySnapshot 和 doc),所以我认为这会搞砸一切。如果你在 querySnapshot 上循环,那么你不应该在循环内再次重用 querySnapshot。

此外,为避免头痛和回调地狱,请使用 await 而不是 .then( .then( .then( .then())))。您不能在方法(.filter()、.map()、.forEach() 等)中使用await,但可以在for 循环中使用它:

let fetch = async () => {

    const querySnapshot = await firestore()
        .collection("Teams")
        .where("uid", "==", await AsyncStorage.getItem("userID"))
        .get();

    if (querySnapshot.empty) {
        console.log("no documents found");
        return;
    }

    for( let doc of querySnapshot.docs){

        let Teams = doc._data;
        console.log(Teams);
        updateActivity((arr) => [...arr, Teams]);
        console.log(Activity);

        let querySnapshot2 = await doc.ref
            .collection("membersList")
            .where("statut", "==", "en attente")
            .get();

        if (querySnapshot2.empty) {
            console.log("no documents found");
            continue;
        }

        for(let doc2 of querySnapshot2.docs){
            let members = doc2._data;
            console.log("aa", members);
            updateMembersList( arr => [...arr, members]);
            console.log("cc", MembersList);
        }
    }
}

【讨论】:

  • 谢谢!!但我有这个错误:( TypeError: Invalid尝试迭代不可迭代实例。为了可迭代,非数组对象必须有一个 [Symbol.iterator]() 方法。
  • 我不得不承认我不熟悉 Firebase 或 Firestore。不确定返回的元素是否是可迭代的,也许他们需要对数组进行某种转换,比如.toArray() 或其他什么?
  • 经过快速研究,我发现querySnapshot.docs 应该被迭代。答案已更新
  • 将缺少的await 指令应用于两个get() 查询。
  • 哦,没错,我错过了。谢谢:)
猜你喜欢
  • 2021-07-23
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
相关资源
最近更新 更多