Future.wait单个Future报错时如何获取其他Future的返回数据
Flutter 并行异步任务异常时保留正常结果的解决方案
默认Future.wait的原生行为是:任意一个子Future抛出未捕获异常时,整个Future.wait会立即进入失败状态,直接丢弃所有其他子Future的执行结果,这就是你场景下snapshot.data返回null的核心原因。解决这个问题的核心思路是提前捕获每个子Future的异常,不让异常直接透传给Future.wait。
方案1:包装子Future返回统一结果结构体(最常用,推荐)
首先定义通用的结果封装类,不管子Future执行成功还是失败,都返回正常的结构体对象,保证Future.wait永远不会触发顶层异常。
// 通用异步结果封装类 class FutureResult<T> { final T? data; final Object? error; final StackTrace? stackTrace; bool get isSuccess => error == null; bool get isError => error != null; FutureResult.success(this.data) : error = null, stackTrace = null; FutureResult.failure(this.error, this.stackTrace) : data = null; } // 扩展方法简化Future包装调用 extension FutureWrapExtension<T> on Future<T> { Future<FutureResult<T>> wrapToResult() async { try { final result = await this; return FutureResult.success(result); } catch (err, stack) { return FutureResult.failure(err, stack); } } }
修改你的FutureBuilder代码如下:
FutureBuilder( // 对每个子Future做包装,Future.wait不会再触发顶层异常 future: Future.wait([ Future1.wrapToResult(), Future2.wrapToResult(), ]), builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: case ConnectionState.active: case ConnectionState.waiting: return SizedBox(height: 600, child: LoadingIndicator()); case ConnectionState.done: // 所有子Future都已执行完成,逐个判断每个任务的执行状态 final resultList = snapshot.data as List<FutureResult>; final future1Result = resultList[0]; final future2Result = resultList[1]; // 单独处理Future1的结果 if (future1Result.isSuccess) { // 逻辑:使用future1Result.data渲染对应区域 } else { // 逻辑:处理Future1的异常,比如显示占位、重试按钮等 } // 单独处理Future2的结果 if (future2Result.isSuccess) { // 逻辑:使用future2Result.data渲染对应区域 } else { // 逻辑:处理Future2的异常 } // 后续页面渲染逻辑 ... } }, )
方案2:自定义并行任务等待逻辑(适合动态任务数量场景)
如果你不想使用Future.wait,可以自己实现任务计数逻辑,等所有任务执行完成后统一返回结果,本质和方案1的逻辑一致:
Future<List<FutureResult<T>>> waitAllTasks<T>(List<Future<T>> tasks) async { final completer = Completer<List<FutureResult<T>>>(); final results = List<FutureResult<T>>.filled(tasks.length, FutureResult.failure(null, null)); int completedCount = 0; if (tasks.isEmpty) { completer.complete(results); return completer.future; } for (int i = 0; i < tasks.length; i++) { final index = i; tasks[index].then((value) { results[index] = FutureResult.success(value); }).catchError((err, stack) { results[index] = FutureResult.failure(err, stack); }).whenComplete(() { completedCount++; if (completedCount == tasks.length) { completer.complete(results); } }); } return completer.future; }
使用时直接把你的Future列表传入waitAllTasks方法即可,后续处理逻辑和方案1完全一致。
注意事项
不要依赖Future.wait的eagerError参数解决该问题:该参数仅能控制报错时机(设为false时会等所有任务完成后再抛出异常),但你依然无法获取成功执行的子Future的返回值,无法满足需求。
内容的提问来源于stack exchange,提问作者Umut Arpat
相关产品推荐
相关产品推荐

