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

How to wait for forEach to complete with asynchronous callbacks?

提问人:Jeet Agrawal 提问时间:9/3/2020 最后编辑:My CarJeet Agrawal 更新时间:2/9/2023 访问量:14835

问:

示例代码:

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
Flutter dart 异步 回调

评论


答:

59赞 jamesdlin 9/3/2020 #1

Iterable.forEach、 和 旨在对集合的每个元素执行一些代码,以产生副作用。它们接受具有返回类型的回调。因此,这些 .forEach 方法不能使用回调返回的任何值,包括返回的 s。如果您提供的函数返回 ,则该函数将丢失,并且您将无法在完成时收到通知。因此,您不能等待每次迭代完成,也不能等待所有迭代完成。Map.forEachStream.forEachvoidFutureFutureFuture

不要将 .forEach 与异步回调一起使用。

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

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

(一般来说,我建议在除特殊情况外的所有情况下使用普通的 for 循环而不是 .forEachEffective Dart 有一个大致相似的建议

如果你真的喜欢使用语法,并且想连续等待每个语法,你可以使用 Future.forEach(它确实需要返回 s 的回调):.forEachFutureFuture

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)),
]);

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