这是对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
});
})
答案 0 :(得分: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
关键字。使用promise,代码如下所示:
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
});
})
因此,我们首先构建一个所有朋友阅读操作的列表,然后一旦完成所有这些操作,我们构建响应并将其发回。