Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 为什么异步firebase抓取不起作用?(节点JS)_Node.js_Firebase_Google Cloud Firestore_Async Await_Synchronization - Fatal编程技术网

Node.js 为什么异步firebase抓取不起作用?(节点JS)

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

构建nodejsrestapi。 尝试从FireBase集合发送加载数据,然后将其发送给用户(作为API响应)。 问题似乎不是等待firebase获取解决,而是在没有收集数据的情况下发回响应。(尝试使用ASYNC-AWAIT,但不起作用)

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的代码看起来比我的代码更好,向高级开发人员学习总是很好的,谢谢大家!