无需等待即可从异步函数生成器生成值

问题描述

我需要同时运行许多异步函数并在它们完成时产生结果,顺序无关紧要。

这是我在一个简化示例中的内容,当然这不起作用,因为它在移动到下一个请求之前等待每个响应。

 Stream<String> stringGenerator(List<http.Request> requests) async* {
    final httpClient = http.Client();
    for (var req in requests) {
      final response = await httpClient.send(req);
      yield response.headers['example'];
    }
  }

解决方法

你能试试看这对你有用吗?

Stream<String> stringGenerator(List<http.Request> requests) {
  final controller = StreamController<String>();
  final httpClient = http.Client();

  Future.wait(requests.map((req) => httpClient
          .send(req)
          .then((response) => controller.add(response.headers['example']!))))
      .whenComplete(() => controller.close());

  return controller.stream;
}

这样更正确,因为根据 StreamController 的文档,我们不想在侦听事件之前生成事件。这对于内部使用来说真的不是问题,因为 StreamController 会在订阅侦听器之前缓冲事件:

Stream<String> stringGenerator(List<http.Request> requests) {
  final controller = StreamController<String>();
  
  controller.onListen = () {
    final httpClient = http.Client();

    Future.wait(requests.map((req) => httpClient
        .send(req)
        .then((response) => controller.add(response.headers['example']!))))
        .whenComplete(() => controller.close());
  };

  return controller.stream;
}
,

@julemand101 解决方案的通用替代方案,适用于任何类型的期货:

Stream<T> fromFutures<T>(Iterable<Future<T>> futures) {
  var pending = 0;
  var controller = Controller<T>();
  for (var future in futures) {
    pending++;
    future.then((v) {
      controller.add(v);
      if (--pending == 0) controller.close();
    },onError: (e,s) {
      controller.addError(e,s);
      if (--pending == 0) controller.close();
    });
  }
  return controller.stream;
}

您可以使用此指定 stringGenerator 为:

Stream<String> stringGenerator(List<http.Request> requests) async* {
  var client = http.Client();
  yield* fromFutures(requests.map(client.send));
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...