【问题标题】:Firestore Promises Query Collection in For Loop (Nuxt.js)Firestore 在 For 循环 (Nuxt.js) 中承诺查询集合
【发布时间】:2018-12-31 07:41:40
【问题描述】:

我基本上一直在尝试通过迭代 cmets 集合来模拟 Firestore 中的 join 语句,将用户加入评论。我知道当您查询一个集合时,它会返回一个承诺和响应,但是,我不确定如何遍历响应中的文档并在 for 循环中执行另一个查询。

这是一个基本的例子

asyncData ({ params }) {
  var postRef = Firestore.collection('posts').doc(params.post);
  var commentRef = 
    Firestore.collection('posts').doc(params.post).collection('comments');
    return commentRef.orderBy('created_on', 'desc').get().then(snapshot => {
        var comments = []
        snapshot.forEach(doc => {
            var docData = doc.data()
            comments.push({
                comment: { data: doc.data(), id: doc.id }
            })
        })
        return comments
    })
    .then(data => {
        var comments = []
        for(const comment of data) {
            Firestore.collection('users-public').doc(comment.comment.data.created_by).get()
            .then(doc => {
                console.log('Got the User!')
                comments.push( {
                    comment: { data: comment.comment.data, id: comment.comment.id },
                    user: doc.data()
                })
            })
        }
        console.log("Returning!")
        return {comments: comments}
    })
},

当它运行时,它会在控制台记录“Returning!”在“得到用户!”之前因为它们是异步调用。我尝试使用 for...of 但这不起作用。有什么方法可以防止这种情况并在返回之前等待所有异步调用完成?我可以解决对 User 集合的承诺调用并调用 .data() 至关重要,否则我会收到一个循环到 json 错误。

【问题讨论】:

    标签: javascript firebase vue.js promise google-cloud-firestore


    【解决方案1】:

    尝试将所有承诺存储在一个数组中,然后在其上调用Promise.all() 方法。这就像一组 Promise 的包装器,它会在所有 Promise 执行后立即执行回调。

    如果您喜欢这种方法,您的代码将如下所示:

    asyncData({ params }) {
        var postRef = Firestore.collection('posts').doc(params.post);
        var commentRef =
            Firestore.collection('posts').doc(params.post).collection('comments');
        return commentRef.orderBy('created_on', 'desc').get().then(snapshot => {
            var comments = []
            snapshot.forEach(doc => {
                var docData = doc.data()
                comments.push({
                    comment: { data: doc.data(), id: doc.id }
                })
            })
            return comments
        })
            .then(data => {
                var comments = []
                // Declare an empty array, where we'll store all the promises
                var promises = []
                for (const comment of data) {
                    let promise = Firestore.collection('users-public').doc(comment.comment.data.created_by).get()
                    // Push the promise to the array
                    promises.push(promise)
                }
                // Callback on this method will execute once all promises on array have been resolved
                Promise.all(promises).then(users => {
                    console.log("All users fetched!")
                    // users is an array with every promise result for every user query
                    users.forEach(user => {
                        let userId = result.id
                        // Attach user to every comment owned by him
                        comments.filter(comment => {
                            return comment.comment.data.created_by === userId
                        }).map(comment => {
                            comment.user = user.data()
                        })
                    })
                    console.log("Returning!")
                    return { comments: comments }
                })
            })
    }
    

    作为替代方案,您可以使用像 async 这样的库来处理来自异步函数的流。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2014-03-11
      • 2023-03-17
      • 2020-05-14
      • 2015-12-18
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多