You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:54:02