简单版: 当我在Firestore中注册onSnapshot时,有没有办法知道我是否是推送更新的客户端?
详细版本:
打开网页时,它会将onSnapshot回调注册到名为notes
的Firestore集合。然后下载该集合并将其存储在本地数组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
}
})
}
然后我们在本地更新注释并将其推送到数据库。
notes[0] = 'changed contents'
firestore.notesRef.doc(0).set(notes[0])
这会将注释发送到firestore,在远程数据库中更新,然后因为我们已经onSnapshot
注册了notes
我们将触发该事件,获得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
}
})
}
有没有办法检测同一个客户端是否调用了触发set
docChange的modified
?
重点在于:如果用户自己进行了更改,那么他们就不会关心我们应该忽略它的变更广告。如果其他用户进行了更改,则应该为该用户选择是否要更新其本地版本。
根据我的经验,当调用firestore.notesRef.doc(0).set(notes[0])
时,从服务器接收更新需要一些时间。如果本地用户在此时再次修改了注释但尚未将其推送到服务器,则其更改将丢失(由服务器版本覆盖 - 它们上次发送到服务器的版本)。它本质上是一种竞争条件。
那么,当我在Firestore中注册onSnapshot时,有没有办法知道我是否是推送更新的客户端?
答案 0 :(得分:2)
您可以通过以下方式查看是本地还是远程更改:
docChange.doc.metadata.hasPendingWrites
如果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
}
})
}