繁体   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.

我的理解是,当使用具有离线持久性的 Firestore 实时侦听器时,它应该像这样工作:

  1. 当侦听器启动时,回调会触发从本地缓存读取的数据,然后立即尝试从服务器读取数据以确保本地缓存具有最新值。 如果服务器数据与本地缓存匹配,则回调侦听器应该只触发一次从本地缓存读取的数据。
  2. 当数据更改时,回调侦听器会触发从服务器读取的数据。 它使用该数据来更新本地缓存。
  3. 当数据没有改变时,所有对监听器的后续调用都会触发一个回调,并从本地缓存中读取数据。

但是我已经设置了离线持久性,为我的 Firestore 数据创建了一个监听器,并监控了读取的来源......

在我的应用程序中,我看到了从本地缓存中的初始读取(预期),然后是从服务器立即读取的第二次(意外)。 之后所有后续读取都来自服务器(也是意外的)。

在此测试期间,我的数据都没有改变。 所以我希望回调监听器的所有读取都来自本地缓存,而不是服务器。

实际上,我唯一一次从本地缓存中看到读取是在侦听器第一次启动时,但这是意料之中的。

可能是什么问题呢?

PS 为了进行这些“后续调用”,我将导航到我的 SPA 的另一个页面,然后返回到我的组件所在的页面以再次触发它。

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

<template>
  <div v-if="website?.url">{{ website.url }}</div>
</template>

<script setup lang="ts">
import { useLoadWebsite } from '../composables/database';
const website = useLoadWebsite();
</script>

没有什么是错的。 你所描述的完全按照我的预期工作。

Firestore 本地持久性并不意味着完全替代后端。 默认情况下,它是在后端不可用的情况下作为临时数据源。 如果后端可用,则 SDK 将更愿意确保客户端应用程序与其完全同步,并在后端可用时提供所有更新。

如果您想强制查询仅使用缓存而不使用后端,您可以以编程方式将缓存指定为该查询的源

如果您出于某种原因根本不想从服务器进行任何更新,那么您可以完全禁用网络访问

也可以看看:

我弄清楚为什么我得到的结果与预期的不同。

罪魁祸首是{ includeMetadataChanges: true }

docs 中所述,该选项将触发元数据更改的侦听器事件。

因此,侦听器回调也在每次元数据更改时触发,而不仅仅是数据读取和写入,导致我看到奇怪的结果。

删除它后,它开始按预期工作,我通过检查 Firebase 控制台中的使用图来验证它,该图显示了读取和快照侦听器的数量。

这是删除该选项的完整代码:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM