[英]Why does my Firestore listener with offline persistence always read from the server?
I am using Firebase JavaScript Modular Web Version 9 SDK with my Vue 3 / TypeScript app. I am using Firebase JavaScript Modular Web Version 9 SDK with my Vue 3 / TypeScript app.
My understanding is that when using Firestore real-time listeners with offline persistence it should work like this:我的理解是,当使用具有离线持久性的 Firestore 实时侦听器时,它应该像这样工作:
But I have setup offline persistence, created a listener for my Firestore data, and monitored where the reads were coming from...但是我已经设置了离线持久性,为我的 Firestore 数据创建了一个监听器,并监控了读取的来源......
And in my app I see an initial read from the local cache (expected), and then a second immediate read from the server (unexpected).在我的应用程序中,我看到了从本地缓存中的初始读取(预期),然后是从服务器立即读取的第二次(意外)。 And after that all subsequent reads are coming from the server (also unexpected).
之后所有后续读取都来自服务器(也是意外的)。
During this testing none of my data has changed.在此测试期间,我的数据都没有改变。 So I expected all reads from the callback listener to be coming from the local cache, not the server.
所以我希望回调监听器的所有读取都来自本地缓存,而不是服务器。
And actually the only time I see a read from the local cache is when the listener is first started, but this was to be expected.实际上,我唯一一次从本地缓存中看到读取是在侦听器第一次启动时,但这是意料之中的。
What could be the problem?可能是什么问题呢?
PS To make those "subsequent calls" I am navigating to a different page of my SPA and then coming back to the page where my component lives to trigger it again. PS 为了进行这些“后续调用”,我将导航到我的 SPA 的另一个页面,然后返回到我的组件所在的页面以再次触发它。
src/composables/database.ts src/composables/database.ts
export const useLoadWebsite = () => {
const q = query(
collection(db, 'websites'),
where('userId', '==', 'NoLTI3rDlrZtzWCbsZpPVtPgzOE3')
);
const firestoreWebsite = ref<DocumentData>();
onSnapshot(q, { includeMetadataChanges: true }, (querySnapshot) => {
const source = querySnapshot.metadata.fromCache ? 'local cache' : 'server';
console.log('Data came from ' + source);
const colArray: DocumentData[] = [];
querySnapshot.docs.forEach((doc) => {
colArray.push({ ...doc.data(), id: doc.id });
});
firestoreWebsite.value = colArray[0];
});
return firestoreWebsite;
};
src/components/websiteUrl.vue src/components/websiteUrl.vue
<template>
<div v-if="website?.url">{{ website.url }}</div>
</template>
<script setup lang="ts">
import { useLoadWebsite } from '../composables/database';
const website = useLoadWebsite();
</script>
Nothing is wrong.没有什么是错的。 What you're describing is working exactly the way I would expect.
你所描述的完全按照我的预期工作。
Firestore local persistence is not meant to be a full replacement for the backend. Firestore 本地持久性并不意味着完全替代后端。 By default, It's meant to be a temporary data source in the case that the backend is not available.
默认情况下,它是在后端不可用的情况下作为临时数据源。 If the backend is available, then the SDK will prefer to ensure that the client app is fully synchronized with it, and serve all updates from that backend as long as it's available.
如果后端可用,则 SDK 将更愿意确保客户端应用程序与其完全同步,并在后端可用时提供所有更新。
If you want to force a query to use only the cache and not the backend, you can programmatically specify the cache as the source for that query .如果您想强制查询仅使用缓存而不使用后端,您可以以编程方式将缓存指定为该查询的源。
If you don't want any updates at all from the server for whatever reason, then you can disable network access entirely.如果您出于某种原因根本不想从服务器进行任何更新,那么您可以完全禁用网络访问。
See also:也可以看看:
I figured out why I was getting a result different than expected.我弄清楚为什么我得到的结果与预期的不同。
The culprit was { includeMetadataChanges: true }
.罪魁祸首是
{ includeMetadataChanges: true }
。
As explained here in the docs , that option will trigger a listener event for metadata changes.如docs 中所述,该选项将触发元数据更改的侦听器事件。
So the listener callback was also triggering on each metadata change, instead of just data reads and writes, causing me to see strange results.因此,侦听器回调也在每次元数据更改时触发,而不仅仅是数据读取和写入,导致我看到奇怪的结果。
After removing that it started to work as expected, and I verified it by checking it against the Usage graphs in Firebase console which show the number of reads and snapshot listeners.删除它后,它开始按预期工作,我通过检查 Firebase 控制台中的使用图来验证它,该图显示了读取和快照侦听器的数量。
Here is the full code with that option removed:这是删除该选项的完整代码:
export const useLoadWebsite = () => {
const q = query(
collection(db, 'websites'),
where('userId', '==', 'NoLTI3rDlrZtzWCbsZpPVtPgzOE3')
);
const firestoreWebsite = ref<DocumentData>();
onSnapshot(q, (querySnapshot) => {
const source = querySnapshot.metadata.fromCache ? 'local cache' : 'server';
console.log('Data came from ' + source);
const colArray: DocumentData[] = [];
querySnapshot.docs.forEach((doc) => {
colArray.push({ ...doc.data(), id: doc.id });
});
firestoreWebsite.value = colArray[0];
});
return firestoreWebsite;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.