如何在Flutter组件/页面中复用异步请求异常处理并控制后续逻辑?
问题:捕获异常后Future的
then逻辑仍执行,不符合预期 问题背景
现有架构分为:展示用Widget/页面、状态管理Provider、请求发起Service、自定义异常集合,需求是在Widget中结合intl包与BuildContext获取用户语言,展示对应语言的错误提示。当前遇到的问题是:封装Future捕获异常复用逻辑时,触发超时异常后,后续then中的打印语句仍会执行,期望仅当无异常时才执行then内的逻辑。
原因分析
使用catchError捕获异常并处理后,该Future会自动转为已完成状态(即使处理函数无返回值,默认返回Future<void>),因此后续绑定的then会被触发执行。若要让异常继续传递,需调整异常处理的逻辑。
解决方案
方案1:在catchError中重新抛出异常
修改_fetchAllItems函数,在错误处理完成后重新抛出异常,让Future保持失败状态,这样后续的then就不会执行:
Future<void> _fetchAllItems(bool refresh) async { setState(() { _error = null; }); return context .read<DemoProvider>() .fetchAllItems(refresh) .catchError((e) { _onTimeOutError(e); rethrow; // 重新抛出异常,维持Future的失败状态 }, test: (e) => e is CustomTimeoutException); }
此方式下,捕获到CustomTimeoutException时,处理完错误提示后重新抛出异常,_fetchAllItems返回的Future会处于失败状态,后续then逻辑不会触发;未被捕获的异常则正常传递。
方案2:用async/await替代then,逻辑更直观
将按钮点击逻辑中的then替换为async/await,直接在try-catch中处理流程,避免catchError改变Future状态的问题,同时代码可读性更高:
void _onPressed() async { print("Test"); setState(() { _error = null; }); try { await context.read<DemoProvider>().fetchAllItems(true); print("Do something after fetch"); // 仅无异常时执行 } on CustomTimeoutException catch (e) { _onTimeOutError(e); } } void _onPressed2() async { print("Test2"); setState(() { _error = null; }); try { await context.read<DemoProvider>().fetchAllItems(true); print("Do another thing after fetch"); // 仅无异常时执行 } on CustomTimeoutException catch (e) { _onTimeOutError(e); } }
这种方式可以去掉_fetchAllItems的封装,直接在点击逻辑中处理,后续结合intl实现多语言提示时,可直接在catch块中通过BuildContext获取本地化文本:
void _onTimeOutError(dynamic _) { setState(() { _error = AppLocalizations.of(context)!.timeoutErrorMessage; // 从intl获取对应语言的提示 }); }
内容的提问来源于stack exchange,提问作者nck
相关产品推荐
相关产品推荐

