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

Dart中如何等待Map<int,Future<GpxCoordinates>>并获取结果Map?

问题描述

我持有一个Map<int, Future<GpxCoordinates>>对象,其中int类型的键为实体ID,Future内包含调用API获取对应实体ID数据的异步请求。我需要同时发起所有请求并等待它们完成,但当前实现返回的是List<GpxCoordinates>,而我需要的是Map<int, GpxCoordinates>。

当前无法满足需求的代码:

try {
      Map<int, Future<GpxCoordinates>> gpxsCoordinatesToFetch = {};

      for (var tourId in event.toursIds) {
        gpxsCoordinatesToFetch[tourId] = gpxRepository.fetchGpxCoordinates(tourId);
      }

      // 问题:返回类型不符合需求
      final gpxsCoordinates = await Future.wait(gpxsCoordinatesToFetch.values);

      emit(GpxsCoordinatesLoaded(coordinates: gpxsCoordinates));
    } catch (e) {
      debugPrint(e.toString());
      emit(GpxError());
    }
解决方案

方法一:利用键与结果列表的顺序对应关系

Future.wait返回的列表顺序和传入的values顺序完全一致,因此可以通过原Map的键列表来一一匹配构建目标Map:

try {
  Map<int, Future<GpxCoordinates>> gpxsCoordinatesToFetch = {};

  for (var tourId in event.toursIds) {
    gpxsCoordinatesToFetch[tourId] = gpxRepository.fetchGpxCoordinates(tourId);
  }

  // 保存键的顺序,和后续结果列表对应
  final tourIds = gpxsCoordinatesToFetch.keys.toList();
  final coordinatesList = await Future.wait(gpxsCoordinatesToFetch.values);

  // 构建目标Map
  final Map<int, GpxCoordinates> gpxsCoordinates = {};
  for (int i = 0; i < tourIds.length; i++) {
    gpxsCoordinates[tourIds[i]] = coordinatesList[i];
  }

  emit(GpxsCoordinatesLoaded(coordinates: gpxsCoordinates));
} catch (e) {
  debugPrint(e.toString());
  emit(GpxError());
}

方法二:包装Future返回包含ID的结果

让每个Future返回包含实体ID和对应数据的组合,再通过这些组合直接构建Map:

try {
  List<Future<(int, GpxCoordinates)>> futures = [];

  for (var tourId in event.toursIds) {
    // 包装Future,使结果携带ID
    futures.add(
      gpxRepository.fetchGpxCoordinates(tourId)
          .then((coords) => (tourId, coords))
    );
  }

  final results = await Future.wait(futures);
  // 从结果列表快速构建Map
  final gpxsCoordinates = Map.fromEntries(
    results.map((res) => MapEntry(res.$1, res.$2))
  );

  emit(GpxsCoordinatesLoaded(coordinates: gpxsCoordinates));
} catch (e) {
  debugPrint(e.toString());
  emit(GpxError());
}

注:如果你的Dart版本低于3.0,不支持元组语法,可以改用MapEntry或自定义类来承载ID与结果的组合。

方法三:异步串行循环(不推荐)

这种方式会逐个发起请求,失去并行请求的性能优势,仅适合特殊场景:

try {
  final Map<int, GpxCoordinates> gpxsCoordinates = {};

  for (var tourId in event.toursIds) {
    // 串行执行请求,效率较低
    gpxsCoordinates[tourId] = await gpxRepository.fetchGpxCoordinates(tourId);
  }

  emit(GpxsCoordinatesLoaded(coordinates: gpxsCoordinates));
} catch (e) {
  debugPrint(e.toString());
  emit(GpxError());
}

内容的提问来源于stack exchange,提问作者E.Benedos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:27:45