如何在Firebase的CRUD操作中正确捕获错误?断网场景异常排查
问题分析与修复方案
核心问题
- Firebase Storage断网时不会立即抛出错误:
putFile默认自带重试逻辑,断网后会持续尝试上传,不会触发catch块,导致加载器一直处于激活状态。 - 云函数调用的异常未被捕获:
updateJobColumn的.then()未绑定错误处理,这里的异常会直接逃逸,无法触发错误提示。 - 加载状态重置逻辑冗余:函数末尾无条件设置
_isLoading = false,可能干扰异常场景下的状态控制。
修复步骤
1. 给Storage上传添加超时/取消机制
修改putFile调用,添加超时配置,超时后主动取消任务并抛出错误:
_uploadImages(context) async { setState(() { _isLoading = true; }); try { List filesList = []; var imgCount = await _getImageCountPerJob(); for (var photo in _imageFileList!) { final destination = 'job-images/$jobId/img/img_$imgCount'; imgCount++; final ref = FirebaseStorage.instance.ref(destination); var file = File(photo.path); // 创建上传任务并设置超时 UploadTask uploadTask = ref.putFile(file); await uploadTask.timeout(const Duration(seconds: 10)).catchError((error) { uploadTask.cancel(); throw error; }); var imageUrl = await ref.getDownloadURL(); filesList.add(imageUrl); } // ...后续代码
2. 统一捕获所有异常
将updateJobColumn的.then()改为await,让异常能被外层try/catch捕获:
// 替换then为await,确保异常进入外层catch await _cloudFunctions.updateJobColumn( documentId: jobId, fieldNameColumn: jobImagesListColumnt, fieldNameColumnValue: filesList, ); _displaySnackBarMessage("Success uploading images", context); setState(() { _imageFileList = []; _isLoading = false; });
3. 调整加载状态逻辑
移除函数末尾无条件的setState,只在成功完成或捕获到异常时修改状态:
_uploadImages(context) async { setState(() { _isLoading = true; }); try { // ...上传和云函数调用逻辑 setState(() { _imageFileList = []; _isLoading = false; }); } catch (err) { log('上传错误: $err'); _displaySnackBarMessage("Error uploading images", context); setState(() { _isLoading = false; }); } }
4. 可选:监听网络状态
引入connectivity_plus包,在上传前检查网络状态,无网络时直接抛出错误:
import 'package:connectivity_plus/connectivity_plus.dart'; // 在上传逻辑开头添加 var connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult == ConnectivityResult.none) { throw Exception("无网络连接,请检查网络设置"); }
额外说明
- Firebase Storage的重试机制是为了提升上传成功率,但在需要即时反馈的场景下,必须手动限制超时或监听网络状态。
- 使用
await替代.then()能让异步代码逻辑更线性,异常捕获更可靠。
内容的提问来源于stack exchange,提问作者user17281101
相关产品推荐
相关产品推荐

