带子集的Firestore查询

问题描述 投票:0回答:1

这是对Firebase的限制还是我做错了?一切正常,直到我在代码中间添加db.collection('users').doc(friendId).get()...。提前致谢。

const db = admin.firestore();
const friendRef = db.collection('users').doc(id).collection('friends');

friendsList = [];

friendRef.get().then((onSnapshot) => {
    if (!onSnapshot.empty) {
        onSnapshot.forEach((friend) => {

            const friendId = String(friend.data().person_id);

            db.collection('users').doc(friendId).get().then((result) => {
                const firstName = String(result.data().name.first);
                const lastName = String(result.data().name.last);
            })

            const data = {
                personId: friendId,
                firstName: firstName,
                lastName: lastName,
            }

            friendsList.push(data);
        })

        res.send(friendsList);
    } else {
        res.send({
            'message': 'no friends'
        });
    }
}).catch((e) => {
    res.send({
        'error': e
    });
})
javascript firebase google-cloud-functions google-cloud-firestore
1个回答
2
投票

数据是从Firestore异步加载的。这意味着,当您将响应发送回客户端时,尚未从Firestore加载数据。

查看这个的最简单方法是使用一些放置好的日志记录语句:

console.log("Before getting friend");
db.collection('users').doc(friendId).get().then((result) => {
  console.log("Got friend");
})
console.log("After getting friend");

当您运行此代码时,它将打印:

在得到朋友之前

得到朋友后

有朋友

这可能不是您期望日志的顺序。原因是数据可能需要一些时间才能从Firestore返回。因此,它不是阻塞线程,而是继续运行线程,然后在数据可用时调用回调函数。不幸的是,这意味着你的res.send(friendsList)最终会将一个空列表发送回客户端,因为数据尚未加载。

解决方法是使用一堆嵌套回调,使用Promise.all()或ES6的新async / await关键字。使用promises,代码如下所示:

const db = admin.firestore();
const friendRef = db.collection('users').doc(id).collection('friends');

friendRef.get().then((onSnapshot) => {
  var promises = [];

  onSnapshot.forEach((friend) => {
    const friendId = String(friend.data().person_id);    
    promises.push(db.collection('users').doc(friendId).get());
  });

  Promise.all(promises).then((snapshots) => {
    friendsList = [];
    snapshots.forEach((result) => {
      friendsList.push({
        personId: result.id,
        firstName: result.data().name.first,
        lastName: result.data().name.last,
      });
    });
    res.send(friendsList);
  });
}).catch((e) => {
  res.send({
    'error': e
  });
})

因此,我们首先构建一个所有朋友读取操作的列表,然后一旦完成所有这些操作,我们构建响应并将其发回。

© www.soinside.com 2019 - 2024. All rights reserved.