React Native安卓应用Firestore本地缓存读取延迟异常求助
React Native安卓Firestore缓存读取延迟问题解决方案
问题背景
开发React Native安卓应用时,断网状态下强制Firestore使用本地缓存加载群组列表,出现延迟递增异常:
- 首次返回群组页需等待10秒
- 重复切换页面后延迟增至1分钟、8分钟不等
- 仅从展示其他Firestore数据的页面返回时出现延迟,从空白页返回则正常
- 已显式设置
.get({source: 'cache'})强制读取缓存
代码现状
组件加载逻辑
const fetchGroups = async () => { const grps = await firebaseConnector.getGroups(); try { Alert.alert(`${grps.length}`); } catch (error) { Alert.alert('error'); } setGroups([...grps]); }; useFocusEffect( useCallback(() => { fetchGroups(); }, []), );
FirebaseConnector获取群组方法
async getGroups(): Promise<GroupItem[]> { try { var groupsItems: GroupItem[] = []; const grpsPartSnapshot = await firestore() .collection('GroupParticipants') .where('UserId', '==', this.userId) .get({source: 'cache'}); const grpsIds = grpsPartSnapshot.docs.map(x => x.data().GroupId); for (const grpIndex in grpsIds) { var grpId = grpsIds[grpIndex]; var grpInfo = await firestore() .collection('Groups') .doc(grpId) .get({source: 'cache'}); groupsItems.push({ id: grpInfo.id, name: grpInfo.data()?.Name, imageSource: grpInfo.data()?.Image, }); } return groupsItems; } catch (error) { console.error(error); return []; } }
解决方案
1. 并行获取群组文档,消除串行请求延迟
当前代码通过for...in串行读取每个群组文档,即使是缓存操作,串行也会累积延迟。改用Promise.all并行处理所有请求:
async getGroups(): Promise<GroupItem[]> { try { const grpsPartSnapshot = await firestore() .collection('GroupParticipants') .where('UserId', '==', this.userId) .get({source: 'cache'}); const grpsIds = grpsPartSnapshot.docs.map(x => x.data().GroupId); // 并行发起所有缓存读取请求 const groupSnapshots = await Promise.all( grpsIds.map(grpId => firestore() .collection('Groups') .doc(grpId) .get({source: 'cache'}) ) ); // 转换结果 return groupSnapshots.map(grpInfo => ({ id: grpInfo.id, name: grpInfo.data()?.Name, imageSource: grpInfo.data()?.Image, })); } catch (error) { console.error(error); return []; } }
2. 清理其他Firestore页面的资源监听
从现象来看,其他展示Firestore数据的页面可能持有未释放的监听,导致缓存资源竞争。在这些页面的useFocusEffect中,离开时取消所有Firestore监听:
useFocusEffect( useCallback(() => { const unsubscribe = firestore() .collection('OtherCollection') .onSnapshot(() => {}); return () => { // 离开页面时取消监听 unsubscribe(); }; }, []), );
3. 添加缓存读取超时机制
即使指定source: 'cache',Firestore内部可能存在隐性超时逻辑,手动添加超时确保快速返回缓存数据:
// 通用超时工具函数 const withTimeout = <T>(promise: Promise<T>, timeoutMs: number): Promise<T> => { return Promise.race([ promise, new Promise<T>((_, reject) => setTimeout(() => reject(new Error('缓存读取超时')), timeoutMs) ) ]); }; // 修改getGroups中的读取逻辑 async getGroups(): Promise<GroupItem[]> { try { const grpsPartSnapshot = await withTimeout( firestore() .collection('GroupParticipants') .where('UserId', '==', this.userId) .get({source: 'cache'}), 1000 // 1秒超时 ); const grpsIds = grpsPartSnapshot.docs.map(x => x.data().GroupId); const groupSnapshots = await Promise.all( grpsIds.map(grpId => withTimeout( firestore() .collection('Groups') .doc(grpId) .get({source: 'cache'}), 1000 ) ) ); return groupSnapshots.map(grpInfo => ({ id: grpInfo.id, name: grpInfo.data()?.Name, imageSource: grpInfo.data()?.Image, })); } catch (error) { console.error(error); return []; } }
4. 显式验证缓存文档存在性
在读取缓存文档后,先检查文档是否存在,避免Firestore内部不必要的逻辑处理:
// 在并行映射中添加存在性检查 const groupSnapshots = await Promise.all( grpsIds.map(async grpId => { const doc = await firestore() .collection('Groups') .doc(grpId) .get({source: 'cache'}); return doc.exists ? doc : null; }) ); // 过滤掉不存在的文档 return groupSnapshots.filter(Boolean).map(grpInfo => ({ id: grpInfo.id, name: grpInfo.data()?.Name, imageSource: grpInfo.data()?.Image, }));
内容的提问来源于stack exchange,提问作者Сергей
相关产品推荐
相关产品推荐

