【发布时间】:2019-03-28 01:38:36
【问题描述】:
您可以使用 onSnapshot() 方法收听文档。使用您提供的回调的初始调用会立即使用单个文档的当前内容创建文档快照。然后,每次内容更改时,另一个调用会更新文档快照。
我只希望我的监听器在数据更改时触发。我不希望它在应用程序加载时触发,以获取数据的初始状态。有什么建议吗?
【问题讨论】:
-
我会喜欢这个功能的!
标签: firebase google-cloud-firestore
您可以使用 onSnapshot() 方法收听文档。使用您提供的回调的初始调用会立即使用单个文档的当前内容创建文档快照。然后,每次内容更改时,另一个调用会更新文档快照。
我只希望我的监听器在数据更改时触发。我不希望它在应用程序加载时触发,以获取数据的初始状态。有什么建议吗?
【问题讨论】:
标签: firebase google-cloud-firestore
没有。每当您使用 onSnapshot 时,都会进行初始调用以立即获取数据,然后监听更改。
但您可以使用 firebase 提供的以下属性处理其中的逻辑,以检测它是初始调用还是更新触发器。
db
.collection("pets")
.doc(petId)
.onSnapshot(
snapshot => {
let data = snapshot.data()
// either edit, update or delete
if (snapshot.metadata.hasPendingWrites) {
if (snapshot.exists) {
// edit or create logic
}
else{
// delete logic
}
}
},
err => {
console.log(err)
}
)
【讨论】:
对我也有用的是检查 document.readystate,然后选择对快照更改采取行动。像这样-
db.collection("collectionName").onSnapshot( (snapshot) => {
console.log(snapshot.docChanges())
if( ["loaded","interactive", "complete"].indexOf(document.readyState) >=0 ){
<-----Your code to act on the snapshot changes---->
}
基于此处的 readystate 属性文档 - https://www.w3schools.com/jsref/prop_doc_readystate.asp
【讨论】:
在阅读了第一个和第二个解决方案后,我提出了一个似乎可行的解决方案。
首先将变量初始化为true,然后在onSnapshot() 方法中检查此变量是否为true,如果是,则将其更改为false,否则编写检索数据算法。像这样的:
var initState = true;
let observer = records.onSnapshot(docSnapshot => {
console.log(`Received doc snapshot`);
if (initState) {
initState = false;
} else {
if (!docSnapshot.docChanges().empty) {
docSnapshot.docChanges().forEach(function (change) {
//Write here wahtever you want
});
}
}
}, err => {
console.log(`Encountered error: ${err}`);
});
【讨论】:
Firestore 侦听器按其自己的顺序加载,并且“onSnapshot”事件必须始终在初始状态下首先执行。但是,您可以通过添加初始状态变量来处理该行为,例如:
var initState = true;
db.collection('col').doc('id').onSnapshot(....
然后您可以在函数内部验证您不想在应用程序启动时运行的代码。
var initState = true;
db.collection('col').doc('id').onSnapshot(....
if(!initState){ // if is not initial state
//your code
}
并且在应用程序启动后你必须将 initState 更改为 false 并添加一个睡眠/超时功能(因为它可能有一个意外的异步负载)
var initState = true;
db.collection('col').doc('id').onSnapshot(....
if(!initState){ // if is not initial state
//your code
}
setTimeout(function () { // cause onSnapShot executes first
initState = false;
}, 2000);
【讨论】:
Firestore 侦听器不是这样工作的。您将始终收到与获取或查询相关的文档,然后在此之后更新,只要监听器仍然添加。没有仅接收增量的模式。
如果您只想接收某些数据,您可能想弄清楚如何查询它,例如,通过添加时间戳字段并让客户端仅查询自前一段时间以来发生更改的文档。
【讨论】:
ListenerOptions.getInitialState() 和ListenerOptions.ignoreInitialState() 这样的字段将使onSnapshot() 方法更加灵活,就像'SetOptions.merge()' 一样! Firebaser,这是一个合理的要求吗? :D