我想把我的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
。