Firebase Firestore onSnapshot在为时间戳使用Firestore FieldValue时为nu



我想把我的firestore时间用于我的聊天应用程序。我编码了下面的代码,但有一个关于firestore字段值的问题。

我把我的信息发送到消防仓库,比如:

chatsRef.add({
...m,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
});

一切正常,但当我监听(onSnapshot(引用chatsRef的文档时,createdAt值总是为空,当我检查firestore时,时间设置正确。我想里面有一个异步事件,我必须等待它。我该如何解决这个问题?

chatsRef:

const chatsRef= db.collection("ChatRooms").doc(id).collection("Chat")

我听聊天参考代码:

useEffect(() => {
let x = null;
const unsubscribe = chatsRef
.orderBy("createdAt", "desc")
.limit(10)
.onSnapshot((querySnapshot) => {
const messagesFirestore = querySnapshot
.docChanges()
.filter(({ type }) => type === "added")
.map(({ doc }) => {
const message = doc.data();
x = message;
console.log(x);// I checked my code and the object's createdAt field gets null.
return { ...message, createdAt: message.createdAt.toDate() };
});
appendMessages(messagesFirestore);
// Some irrelevant codes
return () => unsubscribe();
}, []);

另外,我的消息JSON结构是:

Object {
"_id": "a51d2e86-df8d-449e-b41e-73fbd746856f",
"createdAt": t {
"nanoseconds": 26000000,
"seconds": 1616336752
},
"text": "1111",
"user": Object {
"_id": "jack1212312",
"name": "jackAndME",
},
}

上次更改:

useEffect(() => {
let x = null;
const unsubscribe = chatsRef
.orderBy("createdAt", "desc")
.limit(10)
.onSnapshot({ includeMetadataChanges: true }, (querySnapshot) => {
const messagesFirestore = querySnapshot
.docChanges()
.filter(({ type }) => type === "added")
.map(({ doc }) => {
const message = doc.data();
if (!doc.metadata.hasPendingWrites) {
x = message;
return { ...message, createdAt: message.createdAt.toDate() };
}
return null;
});
if (messagesFirestore[0]) {
appendMessages(messagesFirestore);
if (latestMessage.current != null) {
if (
new Date(
latestMessage.current["createdAt"]["seconds"] * 1000 +
latestMessage.current["createdAt"]["nanoseconds"] / 1000000
) >
new Date(
x["createdAt"]["seconds"] * 1000 +
x["createdAt"]["nanoseconds"] / 1000000
)
) {
latestMessage.current = x;
}
} else {
latestMessage.current = x;
}
}
});
return () => unsubscribe();
}, []);

注意:现在,我可以检测元数据,但无法使用快照访问数据的最后版本。

Firebase医生说:

1- A change event is immediately fired with the new data. The document has not yet been written to the backend so the "pending writes" flag is true.
2- The document is written to the backend.
3- The backend notifies the client of the successful write. There is no change to the document data, but there is a metadata change because the "pending writes" flag is now false. 

但是,当元数据写入后端而不刷新页面时,我无法访问pendingwrites标志——快照没有获得数据。

这是由于Firebase所称的"延迟补偿":

应用程序中的本地写入将立即调用快照侦听器。这是因为一个被称为";延迟补偿"当您执行写入时,您的侦听器将收到新的将数据发送到后端之前的数据。

您的快照在离开应用程序之前被触发,时间戳字段将为null,然后在到达设置了时间戳的后端后再次被触发。

要区分两者,请使用文档中所述的字段metadata.hasPendingWrites

最新更新