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 之前检查了网络活动,但碰巧什么也没有发生,没有创建任何流,所以:
与我在 chrome macbook 上获得的网络日志相比,确实存在网络请求,带有“通道”:
另请注意,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 方法中的错误吗?
我最终使用了这个插件,它在电容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));
}
}
};
});
}