dart 如何等待Map&lt;int,Future< T>&gt;?

ctrmrzij  于 2023-06-19  发布在  其他
关注(0)|答案(3)|浏览(161)

我有一个Map<int, Future<GpxCoordinates>>,其中int键是实体的id,future包含对API的异步调用,以获取相关实体id的数据。
我需要一起启动所有请求,然后等待它们。
这是我的不工作的实现:

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

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

      // Problem in the return await type
      final gpxsCoordinates = await Future.wait(gpxsCoordinatesToFetch.values);

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

问题是Future.await返回List<GpxCoordinates>,但我需要返回Map<int, GpxCoordinates>。是否存在一种方法来获得所需的Map<int, GpxCoordinates>一旦所有的请求已经完成?

wvyml7n5

wvyml7n51#

您必须以某种方式将接收到的数据与ID连接起来。这是实现它的方法之一:

try {
  final Map<int, String> values = {};
  final List<Future> futures = [];
  for (var tourId in [1, 2]) {
    futures.add(Future.microtask(() async {
      // Do the call here
      final String value = await Future.value('some value');

      values[tourId] = value;
    }));
  }

  await Future.wait(futures);

  print(values);
} catch (e) {
  // ...
}

输出:{1: some value, 2: some value}
另一个(可能更好):

...
for (var tourId in [1, 2]) {
  futures.add(
    Future.value('some value').then((value) => values[tourId] = value),
  );
}
...
nlejzf6q

nlejzf6q2#

更换

// Problem in the return await type
  final gpxsCoordinates = await Future.wait(gpxsCoordinatesToFetch.values);

Map<int,GpxCoordinates> gpxsCoordinates = {};
for (final mapEntry in gpxsCoordinatesToFetch.entries) {
   final key = mapEntry.key;
   final futureVal = mapEntry.value;
   gpxsCoordinates[key] = await futureVal;
}

**编辑:**您可以通过使用第三方库或创建一个函数来完成此操作。

上面的例子可以重写为

...
Map<int,GpxCoordinates> gpxsCoordinates = await awaitMap<int,GpxCoordinates>(gpxVal);
...

辅助函数。

Future<Map<R,S>> awaitMap<R,S>(Map<R,Future<S>> myMap) async {
  Map<R, S> res = {};
  for (final mapEntry in myMap.entries) {
    final key = mapEntry.key;
    final val = mapEntry.value;
    res[key] = await val;
  }
  return res;
}
wbrvyc0a

wbrvyc0a3#

您可以使用:

final gpxsCoordinatesList = await Future.wait(
  gpxsCoordinatesToFetch.entries.map((e) {
    return (() async => {e.key: await e.value})();
  }),
);
final gpxsCoordinates = {
  for (final e in gpxsCoordinatesList) e.keys.first: e.values.first
};

它看起来可能有点混乱,但是,我们只是将**<int, Future<GpxCoordinates>>的每个条目Map到一个返回Future<int, GpxCoordinates>**的函数并调用该函数。
然后将List<Map<int, GpxCoordinates>>更改为Map<int, GpxCoordinates>

相关问题