Flutter中Firestore指定缓存获取数据时服务不可用的解决方法
Firestore离线缓存获取数据报错解决方案
问题场景
使用Source.cache从Firestore缓存获取文档时抛出错误:
The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff
已配置persistenceEnabled: true但问题仍存在,使用无参数的.get()则可正常获取数据。
相关代码:
Future<dynamic> fetchFieldValue({ required String collectionPath, required String documentPath, required String targetFieldKey, }) async { final documentSnapshot = await _firebaseFirestore .collection(collectionPath) .doc(documentPath) .get(const GetOptions(source: Source.cache)); // 此处抛出错误 return documentSnapshot.get(targetFieldKey); }
void configureOfflinePersistence() { _firebaseFirestore.settings = const Settings(persistenceEnabled: true); }
解决方法
1. 处理缓存不存在的情况
指定Source.cache时,若目标文档未被缓存过(从未成功获取过或缓存已失效),会直接抛出错误;而无参数.get()会自动先尝试网络再 fallback 到缓存。因此需要在代码中捕获缓存未命中的异常,切换到网络获取:
Future<dynamic> fetchFieldValue({ required String collectionPath, required String documentPath, required String targetFieldKey, }) async { try { final documentSnapshot = await _firebaseFirestore .collection(collectionPath) .doc(documentPath) .get(const GetOptions(source: Source.cache)); return documentSnapshot.get(targetFieldKey); } catch (e) { // 缓存未命中或缓存服务不可用时,切换到网络获取 final documentSnapshot = await _firebaseFirestore .collection(collectionPath) .doc(documentPath) .get(); return documentSnapshot.get(targetFieldKey); } }
2. 确保离线持久化初始化时机正确
离线持久化设置必须在Firestore实例创建后、发起任何请求前完成,否则配置不会生效。调整初始化逻辑:
final FirebaseFirestore _firebaseFirestore = FirebaseFirestore.instance; void initFirestore() { // 立即配置离线持久化 _firebaseFirestore.settings = const Settings(persistenceEnabled: true); // 后续再执行数据请求操作 }
3. 预取文档到缓存
如果业务场景需要依赖缓存数据,可在联网时提前监听或获取文档,让Firestore自动将数据同步到缓存:
void prefetchDocument(String collectionPath, String documentPath) { // 监听文档快照,自动同步到缓存 _firebaseFirestore .collection(collectionPath) .doc(documentPath) .snapshots() .listen((_) {}); }
4. 添加重试机制处理临时异常
错误提示表明这是临时状态,可添加重试逻辑,在重试失败后再切换到网络获取:
Future<dynamic> fetchFieldValue({ required String collectionPath, required String documentPath, required String targetFieldKey, int retryCount = 3, }) async { try { final documentSnapshot = await _firebaseFirestore .collection(collectionPath) .doc(documentPath) .get(const GetOptions(source: Source.cache)); return documentSnapshot.get(targetFieldKey); } catch (e) { if (retryCount > 0 && e.toString().contains("service is currently unavailable")) { // 延迟后重试 await Future.delayed(const Duration(milliseconds: 500)); return fetchFieldValue( collectionPath: collectionPath, documentPath: documentPath, targetFieldKey: targetFieldKey, retryCount: retryCount - 1, ); } // 重试失败或非临时异常,切换到网络获取 final documentSnapshot = await _firebaseFirestore .collection(collectionPath) .doc(documentPath) .get(); return documentSnapshot.get(targetFieldKey); } }
内容的提问来源于stack exchange,提问作者sub
相关产品推荐
相关产品推荐

