简体   繁体   中英

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. 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.

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. 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

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. 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. You should use Promise.all to combine them into a single promise, and then await that promise to get the array of comment replies:

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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