为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕慕森 2022-10-21 15:27:08
我想构建一个以 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 [];            }问题是该函数为每个答案返回了空的回复数组。它跳过了检索每个答案的回复的请求。任何人都可以帮助我吗?还是有更好的风格来实现它?
查看完整描述

1 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

我终于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

    })


  })


}


查看完整回答
反对 回复 2022-10-21
  • 1 回答
  • 0 关注
  • 124 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号