我正在编写一个基于Web的应用程序,允许用户交换有关特定主题的消息。我使用Firebase作为后端,数据存储在Firestore中。存储的消息是一个相当简单的对象,它大致包含一个ID,内容和两个基于服务器的时间戳(作为创建时间和lastupdate时间)。我使用valueChange()方法收听更改。每次我使用set()方法向firestore添加新的消息对象时,都会收到两次更新,而不是预期的一次。 这是正常行为吗?是否将serverTimestamp的创建视为数据的更新,这就是为什么我收到两个事件的原因?
在我的代码下面。单击网页上的按钮即可触发功能getData()。
@Component({
selector: 'app-access',
templateUrl: './access.component.html',
styleUrls: ['./access.component.scss']
})
export class AccessComponent implements OnInit {
m: Message;
subscription: Subscription;
constructor(
private _db: AngularFirestore,
private _auth: AuthService) { }
ngOnInit(): void {
console.log('START...');
this.subscription = this._db.collection<any>(MESSAGES_ENDPOINT).valueChanges()
.subscribe((response) => {
console.log('data received: ', response);
});
}
getData(): void {
this.m = {
id: this._db.createId(),
title: ' Just a test',
message: 'MESSAGE ' + new Date().getSeconds(),
type: 1,
topic: '999999',
state: 0,
from: this._auth.getUserID(),
fromAvatar: this._auth.getAvatar(),
fromDisplayName: this._auth.getDisplayName(),
to: 'JOE COOL',
created: firebase.firestore.FieldValue.serverTimestamp(),
lastUpdate: firebase.firestore.FieldValue.serverTimestamp()
};
this._db.collection<Message>(MESSAGES_ENDPOINT).doc(this.m.id).set(this.m)
.then(() => console.log('Document successfully stored'))
.catch((error) => console.error('Error writing document: ', error));
}
}
结果,我收到以下输出:
START...
access.component.ts:30 data received:
(2) [{…}, {…}] <== **after subscription, returns data already stored in database **
access.component.ts:30 data received: <== ** after submission of new entry, surprisingly **the timestamp fields are null**
(3) [{…}, {…}, {…}]
0: {created: Timestamp, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "Da7Bpaw2Y4ZzSqa44eqb", …}
1: **{created: null**, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "HeY4dqqhwVEUgNIpczCo", …}
2: {created: Timestamp, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "RyDq5pwW0DvnErXH6J2M", …}
length: 3
__proto__: Array(0)
access.component.ts:30 data received: <== ** Second update, this time with correct timestamp fields
(3) [{…}, {…}, {…}]
0: {created: Timestamp, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "Da7Bpaw2Y4ZzSqa44eqb", …}
1: {**created: Timestamp**, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "HeY4dqqhwVEUgNIpczCo", …}
2: {created: Timestamp, from: "R1qkoc1LPefeNTO1fdSKnBJbHE92", fromAvatar: "/assets/images/avatars/avatar_placeholder.png", fromDisplayName: "Guest", id: "RyDq5pwW0DvnErXH6J2M", …}
length: 3
__proto__: Array(0)
答案 0 :(得分:0)
这是正常现象。 SDK会为任何本地侦听器猜测时间戳的值,该本地侦听器会在其任何文档因任何原因发生更改时被触发。然后,当从服务器得知实际值时,将使用新值再次触发侦听器。
如果您不希望本地更新,而只希望来自服务器的本地更新,则必须为查询指出您仅对文档快照感兴趣,而直接来自服务器。我不知道AngularFire是如何公开的,但是在纯JavaScript版本的SDK中,您可以查看SnapshotMetadata的hasPendingWrites属性。您可以通过指示要[在查询中接收元数据更改] [2]来获取快照元数据。