Javascript 如何查询firebase并输出异步结果?

Javascript 如何查询firebase并输出异步结果?,javascript,node.js,firebase,google-cloud-firestore,google-cloud-functions,Javascript,Node.js,Firebase,Google Cloud Firestore,Google Cloud Functions,今天我到处都在找,弄得头昏眼花,真的不知道该怎么办 我正在尝试做一些听起来简单的事情。然而,异步工作流让我崩溃了 从Firestore中的爬网作业中查找每个ID 获取其他集合中这些ID的所有文档 将输出添加到数组中 返回数组的输出 因为所有的东西都是异步的,所以我一直停留在第2和第3条上,因为第4条的执行速度比异步代码要快 我的大问题是,我该如何处理 以下是我的全部功能: exports.publicOutput = functions .region("us-central1&q

今天我到处都在找,弄得头昏眼花,真的不知道该怎么办

我正在尝试做一些听起来简单的事情。然而,异步工作流让我崩溃了

  • 从Firestore中的爬网作业中查找每个ID
  • 获取其他集合中这些ID的所有文档
  • 将输出添加到数组中
  • 返回数组的输出
  • 因为所有的东西都是异步的,所以我一直停留在第2和第3条上,因为第4条的执行速度比异步代码要快

    我的大问题是,我该如何处理

    以下是我的全部功能:

    exports.publicOutput = functions
      .region("us-central1")
      .runWith(runtimeOpts)
      .https.onRequest(async (req, res) => {
        const projectAlias = req.query.projectalias;
        const apiKey = req.query.apikey;
        let status = 404;
        let data = {
          Message:
            "Unauthorized access! Please provide the correct authentication data.",
        };
        let response = data;
        let scrapeStorage = [];
    
        // check if credentials are provided
        if (!projectAlias || !apiKey) {
          return res.status(status).send(response);
        }
    
        // when both items provided execute this
        if (projectAlias && apiKey) {
          const snapshot = await db
            .collection("AdaProjects")
            .where("projectAlias", "==", projectAlias)
            .where("hasAccess", "array-contains", apiKey)
            .limit(1)
            .get();
    
          if (snapshot.empty) {
            return res.status(status).send(response);
          }
    
          if (!snapshot.empty) {
            snapshot.forEach((doc) => {
              projectData = doc.data();
            });
    
            status = 200;
          }
    
          const crawlJobIDs = projectData.crawlJobs;
    
          let scrapeIDs = []; 
    
          crawlJobIDs.forEach(async (jobID) => {
            const snapshot = await db
              .collection("scrapes")
              .where("crawlJobID", "==", jobID)
              .get();
    
            if (snapshot.empty) {
              console.log("not found jobID", jobID);
              return;
            }
    
            snapshot.forEach((doc) => {
              scrapeIDs.push(doc.id);
              console.log(scrapeIDs); // here everything is fine. But this outputs (logically) after "DONE"
            });
    
          });
          
          response = scrapeIDs;
        }
    
        console.log("DONE");
        return res.status(status).send(response);
      });
    
    我还尝试将所有内容放入函数中,并在函数结束之前等待它

     async function getAllScrapeIDs(crawlJobIDs) {
          let someData = [];
          try {
            crawlJobIDs.forEach(async (jobID) => {
              const snapshot = await db
                .collection("scrapes")
                .where("crawlJobID", "==", jobID)
                .get();
    
              if (snapshot.empty) {
                console.log("not found jobID", jobID);
                return;
              }
    
              snapshot.forEach((doc) => {
                someData.push(doc.id);
              });
            });
          } catch (error) {
            console.log(error);
            return null;
          }
    
          return someData;
        }
    
    // and then later in the code 
    const crawlJobIDs = projectData.crawlJobs;
    response = await getAllScrapeIDs(crawlJobIDs);
    
    响应仍然为空,因为异步代码仍然没有更新

    我还尝试在没有async/await的情况下编写所有内容,并应用了.then.catch选项。输出相同。我的函数在用我想要输出的数据填充数组之前完成


    我发现这是一个令人费解的问题,因为这部分
    const crawlJobIDs=projectData.crawlJobs实际上正在工作。可能是因为它只搜索一项?

    在forEach循环中使用async/await不是一个好主意,请参阅和

    您应使用以下方法:

        const crawlJobIDs = projectData.crawlJobs;
    
        let scrapeIDs = [];
    
        let promises = [];
    
        crawlJobIDs.forEach((jobID) => {
            promises.push(db
                .collection("scrapes")
                .where("crawlJobID", "==", jobID)
                .get());
        });
    
        const snapshot = await Promise.all(promises);  
    
        // snapshot is an Array of QuerySnapshots
        // You need to loop on this Array
    
        snapshot.forEach(querySnapshot => {
            querySnapshot.forEach(documentSnapshot => {
                scrapeIDs.push(documentSnapshot.id);
            });
        });
    
      if (!snapshot.empty) {
        const doc = snapshot.docs[0];
        projectData = doc.data();
      
        status = 200;
      }
    
    我允许您管理快照为空的情况


    此外,您还可以使用另一种方法

      if (!snapshot.empty) {
        snapshot.forEach((doc) => {
          projectData = doc.data();
        });
    
        status = 200;
      }
    
    由于您知道
    查询快照中最多有一个文档(由于
    限制(1)
    ),请执行以下操作:

        const crawlJobIDs = projectData.crawlJobs;
    
        let scrapeIDs = [];
    
        let promises = [];
    
        crawlJobIDs.forEach((jobID) => {
            promises.push(db
                .collection("scrapes")
                .where("crawlJobID", "==", jobID)
                .get());
        });
    
        const snapshot = await Promise.all(promises);  
    
        // snapshot is an Array of QuerySnapshots
        // You need to loop on this Array
    
        snapshot.forEach(querySnapshot => {
            querySnapshot.forEach(documentSnapshot => {
                scrapeIDs.push(documentSnapshot.id);
            });
        });
    
      if (!snapshot.empty) {
        const doc = snapshot.docs[0];
        projectData = doc.data();
      
        status = 200;
      }
    

    这太棒了,雷诺。它立即奏效了。最后一个注释也是一个很好的注释,可以删除一些代码行。还感谢您的参考。我将在forEach循环中使用不异步的精神节点。我想知道这里发生了什么
    crawlJobIDs.forEach((jobID)=>{promises.push(db.collection(“scrapes”).where(“crawlJobID”,“==”,jobID.get());})--是不是icw
    const snapshotGroup=wait Promise.all(promises)。在继续并使用snapshotGroup循环它们之前,它会等待所有承诺都完成?是的,
    Promise.all()
    方法将一个承诺数作为输入,并返回一个承诺数,该承诺数解析为输入承诺数的结果数组。“请参阅一分钟前阅读的内容。”。我将阅读更多关于这个及其用例的内容。再次感谢您的快速回复,并在我的周末开始前节省了时间:)@arnoud,已经这么做了!事实上,他马上就这么做了。还将其标记为答案。也许需要时间?