简体   繁体   English

如何在 node.js 中为 firestore 构建递归异步/等待 function

[英]How to structure a recursive async/await function for firestore in node.js

What I am trying to do:我想做什么:
I am trying to retrieve all comments and their replies from firestore (firebase database) using a recursive method.我正在尝试使用递归方法从 firestore(firebase 数据库)检索所有评论及其回复。 Here is the structure of the data:这是数据的结构:
在此处输入图像描述

What is the problem The parent asynchronous function does not wait for the nested asynchronous function to complete.什么问题父异步function不等待嵌套异步function完成。

getThread = async (req, res) => {
    // Getting comments belonging to thread
    const thread_document = await db.doc(`/Threads/${req.params.threadid}`).get()
    threadData = thread_document.data()
    threadData.threadid = thread_document.id
    const comment_query = await db.collection('Comments').where('threadid', '==', threadData.threadid).get()

    // Getting replies belonging to comments
    for (document of comment_query){
    let commentData = await getReplies(document.id)
    threadData.comments.push(commentData )
    }
  return res.json(threadData)
}

//Recursive function to retrieve replies
getReplies = async (id) => {
    let comment = await db.doc(`/Comments/${id}`).get()
    let commentData = comment.data()
  
    commentData.comment_replies = commentData.replies.map(idx => {
      // The parent async function does not wait for the the async function here to finish.
      // Placing a await keyword here will raise the error 'await is only valid in async functions and the top level bodies of modules' 
      return getReplies(idx)
    })
    console.log(commentData)
    return commentData
}

Given the following example,给定以下示例,
在此处输入图像描述
Since the parent async function does not wait for the nested async function, the order of execution now is A -> B -> a, and a fails to be mapped into commentData and commentData for comment A would end up empty.由于父async function不等待嵌套async function,所以现在的执行顺序是A -> B -> a,a无法映射到commentData ,评论A的commentData最终为空。 Hence, I want to program to do A -> a -> B. To do so, I would like to place a await keyword just before the getReplies like因此,我想编写程序来执行 A -> a -> B。为此,我想在 getReplies 之前放置一个 await 关键字,例如

return await getReplies(idx)

but it will raise the error,但它会引发错误,

await is only valid in async functions and the top level bodies of modules.

Which is confusing as getReplies is already a async function. I've looked into other solutions in stackoverflow but I am not able to get the recursive function working.这令人困惑,因为getReplies已经是异步 function。我研究了 stackoverflow 中的其他解决方案,但我无法使递归 function 工作。 Any insights would be appreciated, thank you.任何见解将不胜感激,谢谢。

commentData.comment_replies = commentData.replies.map(idx => {
  // ...
  return getReplies(idx)
})

This map statement is going to create an array of promises, but not wait for those promises to finish.这条 map 语句将创建一个承诺数组,但不会等待这些承诺完成。 You should use Promise.all to combine them into a single promise, and then await that promise to get the array of comment replies:您应该使用 Promise.all 将它们组合成一个 promise,然后等待 promise 以获取评论回复数组:

const promises = commentData.replies.map(idx => {
  return getReplies(idx);
});
commentData.comment_replies = await Promise.all(promises);

Which is confusing as getReplies is already a async function.这令人困惑,因为 getReplies 已经是一个异步 function。

You were getting that error because the function you're inside is idx => { return getReplies(idx) } , which is not an async function. But putting an await in there is not a solution to your problem anyway.您收到该错误是因为您所在的 function 是idx => { return getReplies(idx) } ,它不是异步 function。但是无论如何都无法解决您的问题。

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

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