在将包含serverTimestamp字段的元素添加到Firestore集合中的事件数量很奇怪

时间:2019-01-30 19:49:04

标签: angular google-cloud-firestore angularfire2

我正在编写一个基于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)

1 个答案:

答案 0 :(得分:0)

这是正常现象。 SDK会为任何本地侦听器猜测时间戳的值,该本地侦听器会在其任何文档因任何原因发生更改时被触发。然后,当从服务器得知实际值时,将使用新值再次触发侦听器。

如果您不希望本地更新,而只希望来自服务器的本地更新,则必须为查询指出您仅对文档快照感兴趣,而直接来自服务器。我不知道AngularFire是如何公开的,但是在纯JavaScript版本的SDK中,您可以查看SnapshotMetadata的hasPendingWrites属性。您可以通过指示要[在查询中接收元数据更改] [2]来获取快照元数据。