Flutter中如何处理Stream异常?以Firestore快照流为例
解决方案
你的现有代码仅能处理文档转换阶段的错误(比如FooDto.fromFirestore解析失败),但无法捕获Firestoresnapshots()流本身抛出的错误(如网络中断、权限不足)——这类错误会直接终止整个流,导致后续无法接收新的快照更新。
要实现「捕获所有错误并发出Left(UnexpectedFailure),同时不终止流」的需求,需要使用StreamTransformer.fromHandlers来同时处理流的数据事件和错误事件:
@override Stream<Either<Failure, List<Foo>>> getStream() { final uid = firebaseAuth.currentUser!.uid; return firestore .collection(FOO_COLLECTION) .doc(uid) .collection(FOO_COLLECTION) .snapshots() .transform(StreamTransformer.fromHandlers( handleData: (querySnapshot, sink) { try { final fooList = querySnapshot.docs .map((doc) => FooDto.fromFirestore(doc).toDomain()) .toList(); sink.add(Right(fooList)); } catch (e, stackTrace) { // 捕获文档解析/转换错误,携带栈信息便于调试 sink.add(Left(UnexpectedFailure(e, stackTrace))); } }, handleError: (error, stackTrace, sink) { // 捕获Firestore流本身的错误(如网络故障、权限拒绝) sink.add(Left(UnexpectedFailure(error, stackTrace))); // 不关闭sink,让流保持活跃——针对可恢复错误(如网络恢复),Firestore会自动重试并继续推送快照 }, )); }
关键说明
- 双维度错误捕获
handleData中的try-catch处理文档解析/转换时的异常,避免单个错误快照导致流中断。handleError捕获Firestore流层面的错误(如网络、权限问题),将其转换为Left事件发出,同时保持流不终止。
- 保留栈信息
在UnexpectedFailure中传入stackTrace,能帮助你快速定位错误根源,建议调整UnexpectedFailure的构造函数支持接收栈参数。 - 流的持续性
不关闭sink的情况下,Firestore针对可恢复错误(如网络断开后重连)会自动重试,流会继续接收后续的快照更新;若遇到不可恢复错误(如永久权限拒绝),流最终仍会终止,但至少你已捕获并发出了错误事件。
内容的提问来源于stack exchange,提问作者Pascal Gehring
相关产品推荐
相关产品推荐

