简体   繁体   English

为什么我的具有离线持久性的 Firestore 侦听器总是从服务器读取?

[英]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 实时侦听器时,它应该像这样工作:

  1. When the listener is started the callback fires with data read from the local cache, and then immediately after it also tries to read from the server to make sure the local cache has up to date values.当侦听器启动时,回调会触发从本地缓存读取的数据,然后立即尝试从服务器读取数据以确保本地缓存具有最新值。 If the server data matches the local cache the callback listener should only fire once with data read from the local cache.如果服务器数据与本地缓存匹配,则回调侦听器应该只触发一次从本地缓存读取的数据。
  2. When data changes, the callback listener fires with data read from the server.当数据更改时,回调侦听器会触发从服务器读取的数据。 It uses that data to update the local cache.它使用该数据来更新本地缓存。
  3. When data doesn't change, all subsequent calls to the listener trigger a callback with data read from the local cache.当数据没有改变时,所有对监听器的后续调用都会触发一个回调,并从本地缓存中读取数据。

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.

相关问题 启用离线持久性 Cloud Firestore - Enable offline persistence Cloud Firestore Firestore 是否不对启用持久性的读取查询中缓存且未更改的文档收费? - Does Firestore not charge for documents that are cached and unchanged in a Read query with persistence enabled? 请求允许使用 Firebase Firestore 的离线持久性(网络)? - Request permission to use offline persistence (web) with Firebase Firestore? Firebase 离线持久性:是否禁用在线连接? - Firebase offline persistence: Does it disable online connectivity? 为什么我的图像没有从 firebase 火库中显示? - Why my images is not showing from firebase firestore? 我应该始终手动分离 Firestore 侦听器吗? - Should I always manually detach the Firestore listener? 当我在 class Android Studio 中从 firestore 获取数据时,为什么我的应用程序出错 - Why does my app error when I am Getting data from firestore in class Android Studio 为什么 Firestore 数据库中的数据在 FirestoreRecyclerAdapter 中返回为“null”? - Why does data from Firestore DB returns as 'null' in FirestoreRecyclerAdapter? 为什么来自 firebase Firestore 的数据没有进入我的视图 | Swift 界面 - Why is the data from firebase Firestore not coming into my view | Swift UI firestore bundle 工具是否需要在客户端启用永久离线缓存 - Does the firestore bundle facility require persistent offline cache in the client to be enabled
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM