Node.js 为什么异步firebase抓取不起作用?(节点JS)
构建nodejsrestapi。 尝试从FireBase集合发送加载数据,然后将其发送给用户(作为API响应)。 问题似乎不是等待firebase获取解决,而是在没有收集数据的情况下发回响应。(尝试使用ASYNC-AWAIT,但不起作用)Node.js 为什么异步firebase抓取不起作用?(节点JS),node.js,firebase,google-cloud-firestore,async-await,synchronization,Node.js,Firebase,Google Cloud Firestore,Async Await,Synchronization,构建nodejsrestapi。 尝试从FireBase集合发送加载数据,然后将其发送给用户(作为API响应)。 问题似乎不是等待firebase获取解决,而是在没有收集数据的情况下发回响应。(尝试使用ASYNC-AWAIT,但不起作用) exports.getChatMessages=async(req、res、next)=>{ const chatId=req.params.chatId 常量getChatData=()=>{ 分贝 .collection(“聊天室”) .doc(chatI
exports.getChatMessages=async(req、res、next)=>{
const chatId=req.params.chatId
常量getChatData=()=>{
分贝
.collection(“聊天室”)
.doc(chatId)
.collection('消息')
.orderBy('timeStamp','asc')
.onSnapshot((快照)=>{
snapshot.docs.forEach(msg=>{
console.log(msg.data().messageContent)
返回{
authorID:msg.data().authorID,
messageContent:msg.data().messageContent,
时间戳:msg.data().timeStamp,
}
})
})
}
试一试{
const chatData=wait getChatData()
console.log(chatData)
res.status(200).json({
消息:“聊天室已找到”,
chatData:chatData
})
}捕捉(错误){
如果(!错误状态代码){
错误状态代码(500)
}
下一个(错误)
}
}
如您所见,我使用了2个console.logs来了解问题所在,终端日志如下所示:
- [](从console.logs(chatData))
- 所有消息(来自console.log(msg.data().messageContent))
在firebase数据真正获取之前,是否有任何方法阻止代码?您只能等待承诺。目前,
getChatData()
没有返回承诺,因此等待它是没有意义的。您试图等待一个固定值,因此它会立即解析并跳到下一行<代码>控制台.log(聊天数据)发生。然后,稍后会发生(快照)=>
回调,但为时已晚
const getChatData = () => new Promise(resolve => { // Return a Promise, so it can be awaited
db.collection('chats')
.doc(chatId)
.collection('messages')
.orderBy('timeStamp', 'asc')
.onSnapshot(resolve) // Equivalent to .onSnapshot((snapshot) => resolve(snapshot))
})
const snapshot = await getChatData();
console.log(snapshot)
// Put your transform logic out of the function that calls the DB. A function should only do one thing if possible : call or transform, not both.
const chatData = snapshot.map(msg => ({
authorID: msg.data().authorID,
messageContent: msg.data().messageContent,
timeStamp: msg.data().timeStamp,
}));
res.status(200).json({
message: 'Chat Has Found',
chatData
})
现在,
getChatData
是这个(短版本):
const getChatData=()=>{
分贝
.collection(“聊天室”)
.doc(chatId)
.collection('消息')
.orderBy('timeStamp','asc')
.onSnapshot((快照)=>{})//里面有些东西
}
这意味着getChatData
函数调用一些数据库查询,然后返回void
(无)。我打赌你会想返回db调用(希望这是一个承诺),这样你的等待
会为你做一些工作。大致如下:
const getChatData=async()=>
分贝
.collection(“聊天室”)
// ...
这与const getChatData=async()=>{return db…}
更新:现在我再次查看了文档,我看到您使用了
onSnapshot
,它用于更新,可以多次触发。第一个电话实际上发出了一个请求,但随后继续监听这些更新。因为这看起来像是一个常规的请求响应,并且您希望它只发生一次—请使用.get()
而不是.onSnapshot()
。否则,这些听众就会留在那里,制造麻烦.get()
返回一个承诺,因此我上面提到的示例修复程序可以很好地工作,您无需更改代码的其他部分。如果我理解正确,您希望发回messages
子集合中存在的所有文档的数组。下面的内容应该可以做到这一点
exports.getChatMessages = async (req, res, next) => {
const chatId = req.params.chatId;
const collectionRef = db
.collection('chats')
.doc(chatId)
.collection('messages')
.orderBy('timeStamp', 'asc');
try {
const chatsQuerySnapshot = await collectionRef.get();
const chatData = [];
chatsQuerySnapshot.forEach((msg) => {
console.log(msg.data().messageContent);
chatData.push({
authorID: msg.data().authorID,
messageContent: msg.data().messageContent,
timeStamp: msg.data().timeStamp,
});
});
console.log(chatData);
res.status(200).json({
message: 'Chat Has Found',
chatData: chatData,
});
} catch (err) {
if (!err.statusCode) {
err.statusCode(500);
}
next(err);
}
};
异步方法返回一个
QuerySnapshot
,您可以调用它来枚举QuerySnapshot
中的所有文档,这不是承诺,因为它需要回调函数(.onSnapshot((快照)=>{
)是的,我看到了。我认为这里不需要这样做,因为它返回一个响应,所以它应该是对FireBase的一次请求。更改了get,添加了一个return语句,并为getChatDat()使用了异步函数,仍然不起作用,看起来getChatData()仍然没有阻止其他代码和console.log(chatData)的执行(如果您不更新代码示例,我们将无法帮助您:)更新了代码,但仍然存在相同的问题:(不可能。我的代码与您的代码完全不同。您不能得到相同的错误。这是我也解释过的完整示例(在结构上进行了一些更新)。如果这不起作用,那么其他地方就出了问题,因为代码对我来说似乎很好(无论数据操作在哪里进行)。它可以工作!,用一些承诺更新了代码(我可以使用等待),将map方法更改为forEach,成功了。@Renaud的代码看起来比我的代码更好,向高级开发人员学习总是很好的,谢谢大家!