如何等待 forEach 完成异步回调?

How to wait for forEach to complete with asynchronous callbacks?

示例代码

Map<String,String> gg={'gg':'abc','kk':'kojk'};

Future<void> secondAsync() async {
  await Future.delayed(const Duration(seconds: 2));
  print("Second!");
  gg.forEach((key,value) async{await Future.delayed(const Duration(seconds: 5));
  print("Third!");
});
}

Future<void> thirdAsync() async {
  await Future<String>.delayed(const Duration(seconds: 2));
  print('third');
}

void main() async {
  secondAsync().then((_){thirdAsync();});
}

输出

Second!
third
Third!
Third!

如你所见,我想使用等到 foreach 地图循环完成然后我想打印 third
预期输出

Second!
Third!
Third!
third

Iterable.forEachMap.forEachStream.forEach 旨在针对 副作用 在集合的每个元素上执行一些代码。他们接受具有 void return 类型的回调。因此,那些.forEach方法不能使用回调编辑的任何值return,包括return编辑Future秒。如果您提供 return 是 Future 的函数,那么 Future 将会丢失,并且您将无法在它完成时收到通知。因此,您不能等待每个迭代完成,也不能等待所有迭代完成。

不要将 .forEach 用于异步回调。

相反,如果您想顺序等待每个异步回调,只需使用普通的for循环:

for (var mapEntry in gg.entries) {
  await Future.delayed(const Duration(seconds: 5));
}

(一般来说,I recommend using normal for loops over .forEach in all but special circumstances. Effective Dart has a mostly similar recommendation。)

如果你真的更喜欢使用.forEach语法并且想连续等待每个Future,你可以使用Future.forEach是否 期望回调 return Futures):

await Future.forEach(
  gg.entries,
  (entry) => Future.delayed(const Duration(seconds: 5)),
);

如果你想让你的异步回调可能运行并行,你可以使用Future.wait:

await Future.wait([
  for (var mapEntry in gg.entries)
    Future.delayed(const Duration(seconds: 5)),
]);

如果尝试将异步函数用作 Map.forEachIterable.forEach 回调(以及许多类似 Whosebug 问题的列表),请参阅 https://github.com/dart-lang/linter/issues/891 获取分析器警告请求.

你可以像这样使用 Future.forEach

main() async {
  print("main start");
  await asyncOne();
  print("main end");
}

asyncOne() async {
  print("asyncOne start");
  await Future.forEach([1, 2, 3], (num) async {
    await asyncTwo(num);
  });
  print("asyncOne end");
}

asyncTwo(num) async
{
  print("asyncTwo #${num}");
}