繁体   English   中英

在 Javascript 中从 Firestore 获取 forEach() 之后的数据

[英]Fetching data after forEach() from Firestore in Javascript

我正在构建一个锻炼 web 应用程序,需要显示每次锻炼要完成多少轮以及每轮有多少锻炼。

由于每次锻炼的轮数和每轮锻炼都不同,因此我将它们设置为 forEach。

但我需要知道回合集合的 docID(显示为“roundID”)才能获得特定的 collections,子集合以显示特定的练习。

目前它没有显示练习,因为我需要等待第一次提取完成,然后使用我无法做到的那个 docId。

我已经尝试使用循环等待,异步但无法让它工作。

目前我的代码是:

Main forEach 获得回合

const Rnds = document.getElementById("rnds");

const roundRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds"));
const unsub = onSnapshot(roundRef, (querySnapshot) => {

     querySnapshot.forEach((doc) => {

          const roundID = doc.id;
          const rounds = doc.data().round;
          const rests = doc.data().rest;

          console.log("Round", roundID);

          Rnds.innerHTML += `
               
               <h2>${rounds}</h2>
                            
               A list of the amount of exercise docs in "exercise" collection
                            
               <p>${rests}</p>
                        `
     });
});

然后,获取轮次的练习

const exerciseRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds", roundID, "exercises"));
const exerciseUnsub = onSnapshot(exerciseRef, (querySnapshot) => {

     querySnapshot.forEach((doc) => {

          const reps = doc.data().rep;
          const names = doc.data().exerciseName;

          console.log("Exercises", doc.data());

     });
});

问题更新

目前我可以获取 go 的回合和正确的练习文档,并显示在控制台中。 我设法让回合显示但无法将练习名称传递给 innerHTML。

// Create Exercise Rounds
const Rnds = document.getElementById("rnds");

const roundRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds"));
      
const roundsUnsub = onSnapshot(roundRef, (querySnapshot) => {
     querySnapshot.forEach((doc) => {

          const DocId = doc.id;
          const rounds = doc.data().roundName;
          const rests = "Rest: " + doc.data().rest;

// Calls the `runQuery` async function to get the exercises documents.
          runQuery(DocId).then((result) => {
          // Initialized an object
                            
               const obj = {};
               const names = obj.exerciseNames;
// Assigns the exercises' documents data to its round collection's documents' Id.
               obj[DocId] = result;
// Logs the constructed object.
               console.log(obj);
// Put your `innerhtml` here.
               Rnds.innerHTML += `
               <h2>${rounds}</h2>
               <p>${names}</p>.  // <- unable to get this to show
               <p>${rests}</p>
               `
          });

     });
});

async function runQuery(documentId) {
     const exerciseRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds", documentId, "exercises")); 

     const querySnapshot = await getDocs(exerciseRef);

     if (!querySnapshot) {
         return null;
     }
     // Returns a map of data (array).
     return querySnapshot.docs.map((doc) => doc.data());
                    
}
roundsUnsub;

有一种方法可以关联或获取练习集的数据,但有几点我想指出:

  1. onSnapshot只监听你在这行代码中查询的所有文档的变化(即rounds集合中的文档):
     const roundRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds"));
  2. 如果练习文档有变化,那么您将无法从中获得实时更新。

要从回合集合中获取实时更新并将练习关联到回合的文档,则必须创建一个异步 function,您应该在主 function 上调用它。请参见下面的代码示例:

const roundRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds"));
  
const unsub = onSnapshot(roundRef, (querySnapshot) => {
  querySnapshot.forEach((doc) => {

    const DocId = doc.id;

    // Calls the `runQuery` async function to get the exercises documents.
    runQuery(DocId).then((result) => {
      // Initialized an object
      const obj = {};
      // Assigns the exercises' documents data to its round collection's documents' Id.
      obj[DocId] = result;
      // Logs the constructed object.
      console.log(obj);
      // Put your `innerhtml` here.
    });
  
  });
});

async function runQuery(documentId) {
  const exerciseRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds", documentId, "exercises"));

  const querySnapshot = await getDocs(exerciseRef);
  if (!querySnapshot) {
    return null;
  }
  // Returns a map of data (array).
  return querySnapshot.docs.map((doc) => doc.data());
}

我添加了一些注释以更好地理解上面的代码。


正如我在上面指出的一些问题,如果你想从你的回合集合中获得实时更新,可以有一些解决方法。 您必须修改添加、更新或删除文档的方式。 首先,您需要向练习集合中添加一个文档,然后将数据更新或设置到新创建的回合的文档中。 请参阅下面的示例代码:

  // Your document ID for rounds collection
  const docId = 'Round 3';
  
  const exercisesRef = collection(db, 'user', uid, 'yourWorkouts', id, 'rounds', docId, 'exercises');
  const roundsRef = doc(db, 'users', uid, 'yourWorkouts', id, 'rounds', docId);
  // Add a document to the rounds and exercises collection. Sets the data to the exercises document.
  addDoc(exercisesRef, { 
  // Your exercises document data 
  }, { merge: true })
  .then (() => {
    // Method above will create a round document but doesn't have data on it (still an invalid document).
    // We need to set or update the document to make it a valid document to be able for a snapshot to read the newly added document.
    setDoc(roundsRef, { 
    // Your Rounds document data 
    }, { merge: true })
    .catch((error) => {
      console.error("Error writing Rounds document: ", error);
    });
  })
  .catch((error) => {
    console.error("Error writing exercises document: ", error);
  });

有关更多相关信息,您可能需要查看此文档:


更新

根据您呈现数据的方式,您只需将 object 分配给一个变量,该变量又返回undefined 您必须先访问 object 并使用for循环,因为练习 collections 可以有多个文档。 请参阅下面的代码:

// Create Exercise Rounds
const Rnds = document.getElementById("rnds");

const roundRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds"));
      
const roundsUnsub = onSnapshot(roundRef, (querySnapshot) => {
     querySnapshot.forEach((doc) => {

          const DocId = doc.id;
          const rounds = doc.data().roundName;
          const rests = "Rest: " + doc.data().rest;

          // Calls the `runQuery` async function to get the exercises documents.
          runQuery(DocId).then((result) => {
               // Initialized an object
                            
               const obj = {};
               // Assigns the exercises' documents data to its round collection's documents' Id.
               obj[DocId] = result;
               
               // Initialize names array to be used in `innerhtml`
               const names = [];
               // Logs the constructed object.
               console.log(obj);

               // Loops your exerciseNames and push it in the `names` array
               for (const exerciseDocument of obj[DocId]) {
                 names.push(exerciseDocument.exerciseNames);
               }

               // Put your `innerhtml` here.
               Rnds.innerHTML += `
               <h2>${rounds}</h2>
               <p>${names}</p>.  // This will now show
               <p>${rests}</p>
               `
          });

     });
});

async function runQuery(documentId) {
     const exerciseRef = query(collection(db, "user", uid, "yourWorkouts", id, "rounds", documentId, "exercises")); 

     const querySnapshot = await getDocs(exerciseRef);

     if (!querySnapshot) {
         return null;
     }
     // Returns a map of data (array).
     return querySnapshot.docs.map((doc) => doc.data());
                    
}
roundsUnsub;

要分隔名称,而不是将名称推入数组,您需要初始化一个字符串并使用<p>标记迭代 html output 并使用+= (加法赋值运算符)将结果赋给变量。 请参阅下面的代码:

    runQuery(DocId).then((result) => {
      // Initialized an object
      const obj = {};
      // Assigns the exercises' documents data to its round collection's documents' Id.
      obj[DocId] = result;

       var names = "";
       for (const exerciseDocument of obj[DocId])
         // Make sure that you type the fieldname correctly.
         // Based on your codes given above, you mentioned `exerciseName` and `exerciseNames`
         names +=`<p>${exerciseDocument.exerciseNames}</p>`;
       }

       Rnds.innerHTML +=
       `<h2>${rounds}</h2>.
       ${names}.
       <p>${rests}</p>`

    });
  
  });

查看此工作片段。 它应该是这样的:

 <.DOCTYPE html> <html> <body> <p id="rnds"></p> <script> const Rnds = document;getElementById("rnds"); const DocId = 'Round' const rounds = DocId: // Sample constructed object based on your Firestore Structure const obj = {Round:[{exerciseNames, 'exercise1'}: {exerciseNames; 'exercise2'}]}; const rests = 'testRest'. var names = "" for (const exerciseDocument of obj[DocId]) { names +=`<p>${exerciseDocument;exerciseNames}</p>`. } Rnds.innerHTML += `<h2>${rounds}</h2>. ${names}. <p>${rests}</p>` </script> </body> </html>

暂无
暂无

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

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