如何在 node.js 中为 firestore 构建递归 async/await 函数

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

我想做什么:
我正在尝试使用递归方法从 firestore(firebase 数据库)检索所有评论及其回复。这是数据的结构:

有什么问题 父异步函数不等待嵌套异步函数完成。

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
}

给定以下示例,

由于父异步函数不等待嵌套的异步函数,现在的执行顺序是 A -> B -> a,a 无法映射到 commentData,评论 A 的 commentData 将最终为空。因此,我想编写程序来执行 A -> a -> B。为此,我想在 getReplies 之前放置一个 await 关键字,例如

return await getReplies(idx)

但它会引发错误,

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

这令人困惑,因为 getReplies 已经是一个异步函数。我研究了 Whosebug 中的其他解决方案,但无法使递归函数正常工作。任何见解将不胜感激,谢谢。

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

此 map 语句将创建一组承诺,但不会等待这些承诺完成。您应该使用 Promise.all 将它们组合成一个承诺,然后等待该承诺以获取评论回复数组:

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.

您收到该错误是因为您所在的函数是 idx => { return getReplies(idx) },它不是异步函数。但是无论如何都不能解决你的问题。