Dart中的异步可迭代映射

Ale*_*kiy 9 dart

我可以使用异步映射功能映射一些Iterable吗?也许这是一个错误,该代码会隐式打印_Future列表,而不是在1或5秒后显示整数吗?

import 'dart:async';

Future<int> foo(int i) {
  var c = new Completer();
  new Timer(new Duration(seconds: 1), () => c.complete(i));
  return c.future;
}

main() {
  var list = [1,2,3,4,5];
  var mappedList = list.map((i) async => await foo(i));
  print(mappedList);
}
Run Code Online (Sandbox Code Playgroud)

Fox*_*x32 10

该表达式(i) async => await foo(i)仍返回未来。您可以Future.wait(mappedList)用来等待所有创建的期货完成。

  • 所以它应该是`ListmappedList=awaitFuture.wait(list.map((i)async=&gt;awaitfoo(i)));`。 (13认同)

Ben*_*non 9

其他答案在我的情况下并没有真正起作用,最终使用rxdartasyncMap是这样的:

Observable.fromIterable(list)
      .asyncMap((item) => foo(item))
      .toList();
Run Code Online (Sandbox Code Playgroud)

编辑:Observablerxdart 0.23.0以来,类已停止使用,您可以像这样使用Streams

Stream
 .fromIterable(list)
 .asyncMap((item) => foo(item))
 .toList();
Run Code Online (Sandbox Code Playgroud)


Ale*_*uin 8

添加一些类型将解释发生了什么:

main() async {
  var list = [1,2,3,4,5];
  Iterable<Future<int>> mappedList = list.map((i) async => await foo(i));
  print(mappedList); // you print an Iterable of Future 

  // to get the list of int you have to do the following
  Future<List<int>> futureList = Future.wait(mappedList);
  List<int> result = await futureList;
  print(result);
}
Run Code Online (Sandbox Code Playgroud)


Gáb*_*bor 8

有了今天的 Dart,就没有问题了。忘记了map,直接构建你的列表:

final list = [for (final item in items) await buildAsync(item)];
Run Code Online (Sandbox Code Playgroud)


Arg*_*tus 5

您的误解是异步函数返回一个Future,而不是一个值。await不会将异步转换为同步。

var mappedList = list.map(
  (i) async => await foo(i) // Returns a Future, not an int
);
Run Code Online (Sandbox Code Playgroud)

您正在打印的是所返回的期货(i) async => await foo(i)

这些期货在其中的期货链完成时完成。当计时器触发时:foo()完成,然后完成,然后执行await foo(i)映射功能。

与之比较:

main() async {
  List<int> list = [1,2,3,4,5];
  Iterable<Future<int>> mapped;

  // Prints ints 1 second apart
  mapped = list.map((i) => foo(i));
  for(Future<int> f in mapped) {
    print(await f);
  }

  // Prints ints all at once, after 1 second wait
  mapped = list.map((i) => foo(i));
  for(Future<int> f in mapped) {
    f.then(print);
  }
}
Run Code Online (Sandbox Code Playgroud)

在Dartpad上:https://dartpad.dartlang.org/151949be67c0cdc0c54742113c98b291

注意事项:

List.map()返回一个懒惰Iterable(不是a List),这意味着直到Iterable迭代通过时才调用映射函数。

第一个循环等待每个Future完成,然后再打印并移至中的下一个项目,打印每个值后将调用Iterable下一个项目的映射函数(因此foo()),因此将以1秒的间隔打印值。

第二个循环Iterable立即循环遍历,设置打印功能以在每次Future完成后执行。一次调用函数foo()的5个实例,它们全部在大约1秒钟后返回,然后打印所有5个值。