如何在 Firestore 中处理多个相关的异步查询

我想构建一个以 Firebase 作为后端的问答应用。Firestore 中有三个集合questions:answers和repliesToAnswers。中的文档question有 1 个字段content,中的文档answers有 2 个字段answerid和content,中的文档repliesToAnswers有 3 个字段answerId,questionId并且content。


questions: {

    content

}



answers: {

    questionId

    content 


}


repliesToAnswers {

    content

    answerId

    questionId 

}


我的目标是构建一个/question/:questionId获取这样的结构化数据的 Restful API 端点


{

    "content": "How to ...",

    "answers": [

        {

            "content":"...",

            "replies": [

                {

                    "content":"..."

                },

                {

                    "content":"..."

                }

            ]

        },

        {

            "content":"...",

            "replies":[]

        }

    ],

}


所以我尝试编写容易出错的嵌套 Promises。



exports.getQuestion = (request, response) => {

  console.log(request.params);


  let questionId = request.params.questionId;

  let question = {};


  firebase

  .firestore()

  .collection('questions')

  .doc(questionId)

  .get()

  .then(doc => {

    if(!doc.exists) {

      throw Error("doc not exists")

    }


    return doc;

  })

  .then(doc => {

    question.username = doc.data().username

    return doc.id 

  })

  .then(id => {

    // retrive answsers 

    let answers = [];


    firebase.firestore()

    .collection('answers')

    .where('questionId', '==', id)

    .get()

    .then(snapshot => {

      if (snapshot.empty) {

        console.log('no answers');

        return answers;

      }

      


      snapshot.forEach(ans => {

        // retrive replies

       

        let replies = [];

        

        firebase.firestore()

          .collection('repliesToAnswers')

          .where('questionId','==',questionId)

          .where('answerId','==', ans.id)

          .get()

          .then(snapshot => {

            if(snapshot.empty) {

              console.log(`no reply to answer(id:${ans.id}) of question(${questionId})`);

              return [];

            }



问题是该函数为每个答案返回了空的回复数组。它跳过了检索每个答案的回复的请求。任何人都可以帮助我吗?还是有更好的风格来实现它?


慕慕森
浏览 126回答 1
1回答

Smart猫小萌

我终于Promise.all()用更优雅的代码解决了这个问题。exports.getQuestion = (request, response) => {  let questionId = request.params.questionId; // let question = {};  //let answers = [];  // get info except answers   // { content:XXX, answers: []  }  let fetchQuestion = firebase.firestore()                      .doc(`questions/${questionId}`)                      .get()                      .then(doc => {                        if(!doc.exists) {                          throw Error('doc not exists');                        }                        return doc                       })                      .then(doc => {                        return {                          content: doc.data().content,                          id: doc.id,                          answers: []                        }                      })                      .catch(error => {                        console.log(error)                      });  // return answers   let fetchAnswers =  firebase.firestore()                      .collection('answers')                      .where('questionId','==',questionId)                      .get()                      .then(snapshot => {                        if(snapshot.empty) {                          console.log('no replies');                           return [];                        } else {                          let answers = [];                           snapshot.forEach(ans => {                            // add answers to question                            answers.push({                              content: ans.data().content,                               replies: [],                               id: ans.id                             })                          })                          return answers;                        }                      }).catch(error => {                        console.log(error);                       });    let fetchAnsReplies = fetchAnswers.then(answers => {    var promises = [];        answers.forEach(ans => {      var promise = firebase.firestore()       .collection('repliesToAnswers')      .where('answerId','==',ans.id)      .get()      .then(snapshot => {        if(snapshot.empty) {          console.log('no reply');          return;        } else {                    snapshot.forEach(reply => {                     ans.replies.push({              content: reply.data()            })          })        }       }).catch(error => {        console.log(error);       })      promises.push(promise);    })    return Promise.all(promises).then(() => {            return answers;    })  }).catch(error => {    console.log(error);  })  return Promise.all([fetchQuestion,fetchAnswers, fetchAnsReplies])  .then(results => {    return response.json({...results[0],answers:results[2]});  }).catch(error => {    console.log(error);    response.status(500).json({      error: error.code    })  })}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript