Firestore onSnapshot 更新事件是否由于本地客户端设置?

Mat*_*ane 4 firebase google-cloud-firestore

简单版: 当我在 Firestore 中注册 onSnapshot 时,有没有办法知道我是否是推送更新的客户端?

详细版本:
当打开网页时,它会将 onSnapshot 回调注册到名为 的 Firestore 集合notes。然后将集合下载并存储在本地数组中var notes = []

var window.notes = []
let notesRef = refs.db.collection('notes')
notesRef.onSnapshot(querySnapshot => {
  querySnapshot.docChanges.forEach((docChange) => {
    switch (docChange.type) {
      case 'added':
        notes.push(docChange.doc.data())
        break
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

然后我们在本地更新笔记并将其推送到数据库。

notes[0] =  'changed contents'
firestore.notesRef.doc(0).set(notes[0])
Run Code Online (Sandbox Code Playgroud)

这将发送注释出公司的FireStore,在远程数据库中更新,然后因为我们注册onSnapshotnotes集合,我们将触发该事件,并得到了modified改变。

let notesRef = refs.db.collection('notes')
notesRef.onSnapshot(querySnapshot => {
  querySnapshot.docChanges.forEach((docChange) => {
    switch (docChange.type) {
      case 'added':
        notes.push(docChange.doc.data())
        break
      case 'modified':
        // ********** We end up here!!! ***********
        // Probably want to do:
        notes[docChange.doc.id] = docChange.doc.data()
        break
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

有没有办法检测这个客户端是否调用了set触发modifieddocChange 的 ?
关键是:如果用户自己进行了更改,那么他们不关心更改广告,我们应该忽略它。如果其他用户进行了更改,则应让该用户选择是否要更新其本地版本。

根据我的经验,firestore.notesRef.doc(0).set(notes[0])调用when需要一些时间才能从服务器接收更新。如果本地用户此时再次修改了笔记但尚未将其推送到服务器,则他们的更改将丢失(被服务器版本覆盖 - 他们上次发送到服务器的版本)。这本质上是一种竞争条件。

那么,当我在 Firestore 中注册到 onSnapshot 时,有没有办法知道我是否是推送更新的客户端?

Mat*_*ane 6

您可以通过以下方式查看它是本地更改还是远程更改:

docChange.doc.metadata.hasPendingWrites
Run Code Online (Sandbox Code Playgroud)

如果hasPendingWrites为真,则更新的来源是本地的。本地缓存已更新,对服务器的写入仍处于挂起状态。如果hasPendingWrites为 false,则更新的来源是远程的。

onSnapshot在此代码段中查看如何使用它:

let notesRef = refs.db.collection('notes')
notesRef.onSnapshot(querySnapshot => {
  querySnapshot.docChanges.forEach((docChange) => {
    switch (docChange.type) {
      case 'added':
        notes.push(docChange.doc.data())
        break
      case 'modified':
        // ********** New Code ***********
        let source = docChange.doc.metadata.hasPendingWrites ? 'Local' : 'Server'
        if (source === 'Server') {
          notes[docChange.doc.id] = docChange.doc.data()
        } else {
          // Do nothing, it's a local update so ignore it
        }
        // ********** New Code End ***********
        break
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

  • 有什么方法可以知道服务器的文档更新是否是由于客户端发起的_transaction_引起的? (2认同)