簡體   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