Angular/Fire docData 适用于 chrome/safari macos,但绝不会在 Capacitor-ios 上发出

问题描述 投票:0回答:1

Angular/Fire 方法 docData 适用于 chrome/safari macos,但绝不会在 Capacitor-ios 上发出(Capacitor 在 ios 上使用 webkit-safari)

我可以看到游戏对象确实存在,因为它在我的桌面浏览器上显示并出现,我什至可以在我的 Capacitor-ios-native-app 上与该对象交互,但只是无法接收任何流更新。游戏文档引用控制台日志也正确记录了游戏,因此错误确实需要位于 docData 函数内(?)

所有其他操作,如读/写/删除(无流)都可以在 ios 上运行。

任何调试提示将不胜感激。

这是我的代码,请记住这在桌面上完美运行。

const gameDocRef = doc(this.firestore, 'game', game.id);
if (showGameLogs) {
  let toLog: any = (gameDocRef as any)._key;
  console.log("gameDocRef:", gameDocRef);
  console.log("🟩 CALLING DOC_DATA ON THIS GAME DOC REF:", toLog?.path?.segments);
}
const game$ = docData(gameDocRef, { idField: 'id' }).pipe(
  map(data => {
    if (showGameLogs) {
      console.log("🟩 docData EMISSION:", data);
    }
    if (data === undefined) {
      return null;
    } else {
      return data;
    }
  })
) as Observable<Game | null>;

我在 ios 上调用 docData 之前检查了网络活动,但碰巧什么也没有发生,没有创建任何流,所以:

enter image description here

与我在 chrome macbook 上获得的网络日志相比,确实存在网络请求,带有“通道”:

enter image description here

另请注意,firestore 有一个自定义电容器插件,但它没有像 docData 这样返回可观察值的函数。它只有一个通过回调方法执行此操作的函数。而且该插件并未广泛使用,因此我更愿意坚持使用更流行的 Angular/Fire 库。

电容器 ios 的最小可重现示例对我来说很难创建,当然也很难对您进行测试,但一旦有人回答我的其他最小可重现示例问题(请参阅我的帐户上一个问题),我就会创建一个。

更新:

我用裸露的 Web-modular-api 编写了自己的自定义 docData 函数,但它仍然没有在 ios 本机电容器上创建通道(但在桌面 chrome/safari 上完美运行):

import { onSnapshot } from "firebase/firestore";

function docData<T>(docRef: DocumentReference<T>, options?: { idField?: string }): Observable<T> {
  return new Observable<T>(observer => {
    const unsubscribe = onSnapshot(docRef,
      (docSnapshot) => {
        if (docSnapshot.exists()) {
          const data = docSnapshot.data() as T;
          if (options?.idField) {
            (data as any)[options.idField] = docSnapshot.id;
          }
          observer.next(data);
        } else {
          observer.next(undefined as any);
        }
      },
      (error) => {
        console.error("Error fetching document:", error);
        observer.error(error);
      }
    );
    return { unsubscribe };
  });
}

即使这样做也不会执行任何操作,但仅在电容器-ios 上(它始终在桌面 safari/chrome 上记录):

onSnapshot(gameDocRef, () => console.log("EMISSION DETECTED"));

为什么这没有创建通道,即使我可以清楚地调用 onSnapshot?这是 firebase/firestore web sdk onSnapshot 方法中的错误吗?

javascript angular firebase ionic-framework capacitor
1个回答
0
投票

我最终使用了这个插件,它在电容ios上解决了这个问题:

https://github.com/capawesome-team/capacitor-firebase/tree/main/packages/firestore

请注意,该库并没有解决根本问题,而是使用 firebase 的本机 IOS/Android API,这也带来了性能改进。在这里阅读更多内容:

https://capawesome.io/blog/announcing-the-capacitor-firebase-cloud-firestore-plugin/

这就是我使用这个插件的方式,模仿 Angular/Fire docData 函数返回一个可观察的值。我尝试获取与 Angular docData 函数相同的 API。但请谨慎使用下面的代码,因为我没有彻底测试它:

import {
  AddDocumentSnapshotListenerCallback,
  AddDocumentSnapshotListenerOptions,
  CallbackId, DocumentData,
  FirebaseFirestore, RemoveSnapshotListenerOptions
} from '@capacitor-firebase/firestore';

function docData<T extends DocumentData>(docRef: DocumentReference<T>, options?: { idField?: string }): Observable<T | null> {
  return new Observable<T | null>(observer => {
    let callbackId: CallbackId;

    const listenerOptions: AddDocumentSnapshotListenerOptions = {
      reference: docRef.path
    };

    const callback: AddDocumentSnapshotListenerCallback<T> = (event, error) => {
      if (error) {
        console.error("Error fetching document:", error);
        observer.error(error);
        return;
      }

      if (event && event.snapshot) {
        const data = event.snapshot.data;
        if (data && options?.idField) {
          try {
            (data as any)[options.idField] = event.snapshot.id || null;
          } catch (e) {
            console.error("Error setting idField:", e);
          }
        }
        observer.next(data || null);
      } else {
        observer.next(null);
      }
    };

    FirebaseFirestore.addDocumentSnapshotListener(listenerOptions, callback)
      .then(id => callbackId = id)
      .catch(error => observer.error(error));

    return {
      unsubscribe: () => {
        if (callbackId) {
          const removeOptions: RemoveSnapshotListenerOptions = { callbackId };
          FirebaseFirestore.removeSnapshotListener(removeOptions)
            .catch(error => console.error("Error removing listener:", error));
        }
      }
    };
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.