Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous async*是否延迟调用该函数?_Asynchronous_Dart_Generator - Fatal编程技术网

Asynchronous async*是否延迟调用该函数?

Asynchronous async*是否延迟调用该函数?,asynchronous,dart,generator,Asynchronous,Dart,Generator,在为我的项目编写一些单元测试时,我遇到了一个有趣的问题 以下是用户可用于放置标记的地图: class DomainMap { static const _DEFAULT_COORDINATE = const Coordinate(40.73, -73.93); final ReverseGeocodingStrategy _geocodingStrategy; final RouteDefinitionStrategy _assemblyStrategy; final List&

在为我的项目编写一些单元测试时,我遇到了一个有趣的问题

以下是用户可用于放置标记的地图:

class DomainMap {
  static const _DEFAULT_COORDINATE = const Coordinate(40.73, -73.93);
  final ReverseGeocodingStrategy _geocodingStrategy;
  final RouteDefinitionStrategy _assemblyStrategy;
  final List<_IdentifiedCoordinate> _addressed = [];
  final List<Coordinate> _markers = [];
  final _Route _route = _Route();

  Coordinate get defaultCoordinate => _DEFAULT_COORDINATE;

  DomainMap(this._geocodingStrategy, this._assemblyStrategy);

  Stream<MarkersUpdateEvent> mark(Coordinate coordinate) async* {
    _markers.add(coordinate);
    yield _assembleMarkersUpdate();
    final Address address = await _geocodingStrategy.geocode(coordinate);
    _addressed.add(_IdentifiedCoordinate(coordinate, address));
    if (_addressed.length > 1) {
      final Iterable<Coordinate> assembledPolyline =
          await _assemblyStrategy.buildRoute(BuiltList(_addressed
              .map((identifiedCoordinate) => identifiedCoordinate.address)));
      assembledPolyline.forEach(_route.add);
      yield _assembleMarkersUpdate();
    }
  }

  MarkersUpdateEvent _assembleMarkersUpdate() =>
      MarkersUpdateEvent(BuiltList.from(_markers), _route.readOnly);
}

class _Route {
  final List<Coordinate> _points = [];

  Iterable<Coordinate> get readOnly => BuiltList(_points);

  void add(final Coordinate coordinate) => _points.add(coordinate);

  void addAll(final Iterable<Coordinate> coordinate) => _points.addAll(coordinate);
}
当我像那样运行它时,测试失败,并说流只发出一个值—一个仅带有
标记的更新事件
字段不为空,其中只包含
第二个坐标
。但是当我取消对forEach的注释时,测试通过了

据我所知-
async*
方法在流的值未被请求之前不会被调用,所以当调用
forEach
时,函数将一直执行到最后。因此,如果我请求所有流的(从第一次调用返回的)值—方法执行,
标记
列表填充,第二次执行以预期状态执行


我是否正确理解了
async*
语义?这里有没有一种方法可以让这个函数变得更急切而不是懒惰(我不想请求不需要的流的值)?

是的,
async*
在您对返回的流调用
listen
后,会懒洋洋地调用这个函数。如果你从来不听,那么什么也不会发生。 它甚至异步执行,而不是直接响应
listen
调用

因此,如果您确实需要一些事情发生,但可能只需要查看响应,那么您就不能使用
async*
函数来完成这些事情

您可能想要做的是有条件地填充流,但前提是流确实被监听。 这是一个非传统的操作序列,与
async*
甚至
async
语义不匹配。 您必须为操作的完成做好准备,然后再监听流。这建议将操作分为两部分,一部分用于请求,另一部分用于响应,并在两者之间共享未来,这意味着两次监听同一未来,这是一种明显的非异步行为

我建议将流行为分离出来,并为此使用
StreamController

Stream<MarkersUpdateEvent> mark(Coordinate coordinate) {
  var result = StreamController<MarkersUpdateEvent>();
  () async {
    _markers.add(coordinate);
    result.add(_assembleMarkersUpdate());
    final Address address = await _geocodingStrategy.geocode(coordinate);
    _addressed.add(_IdentifiedCoordinate(coordinate, address));
    if (_addressed.length > 1) {
      final Iterable<Coordinate> assembledPolyline =
          await _assemblyStrategy.buildRoute(BuiltList(_addressed
              .map((identifiedCoordinate) => identifiedCoordinate.address)));
      assembledPolyline.forEach(_route.add);
      result.add(_assembleMarkersUpdate());
    }
    result.close();
  }().catchError(result.addError);
  return result.stream;
}
流标记(坐标){
var result=StreamController();
()异步{
_标记。添加(坐标);
添加(_assembleMarkersUpdate());
最终地址=等待地理编码策略地理编码(坐标);
_地址。添加(_标识的坐标(坐标,地址));
如果(_addressed.length>1){
最终可拼接多段线=
等待装配策略。构建路线(构建列表
.map((identifiedCoordinate)=>identifiedCoordinate.address));
集合多段线.forEach(_route.add);
添加(_assembleMarkersUpdate());
}
result.close();
}().catchError(result.addError);
返回result.stream;
}

这样,程序逻辑独立于是否有人监听流而运行。您仍然需要缓冲所有流事件。没有真正的方法可以避免这种情况,除非您可以在以后计算它们,因为您不知道何时有人可能会侦听返回的流。它不必在返回时立即发生。

是的,
async*
在对返回的流调用
listen
后,延迟调用该函数。如果你从来不听,那么什么也不会发生。 它甚至异步执行,而不是直接响应
listen
调用

因此,如果您确实需要一些事情发生,但可能只需要查看响应,那么您就不能使用
async*
函数来完成这些事情

您可能想要做的是有条件地填充流,但前提是流确实被监听。 这是一个非传统的操作序列,与
async*
甚至
async
语义不匹配。 您必须为操作的完成做好准备,然后再监听流。这建议将操作分为两部分,一部分用于请求,另一部分用于响应,并在两者之间共享未来,这意味着两次监听同一未来,这是一种明显的非异步行为

我建议将流行为分离出来,并为此使用
StreamController

Stream<MarkersUpdateEvent> mark(Coordinate coordinate) {
  var result = StreamController<MarkersUpdateEvent>();
  () async {
    _markers.add(coordinate);
    result.add(_assembleMarkersUpdate());
    final Address address = await _geocodingStrategy.geocode(coordinate);
    _addressed.add(_IdentifiedCoordinate(coordinate, address));
    if (_addressed.length > 1) {
      final Iterable<Coordinate> assembledPolyline =
          await _assemblyStrategy.buildRoute(BuiltList(_addressed
              .map((identifiedCoordinate) => identifiedCoordinate.address)));
      assembledPolyline.forEach(_route.add);
      result.add(_assembleMarkersUpdate());
    }
    result.close();
  }().catchError(result.addError);
  return result.stream;
}
流标记(坐标){
var result=StreamController();
()异步{
_标记。添加(坐标);
添加(_assembleMarkersUpdate());
最终地址=等待地理编码策略地理编码(坐标);
_地址。添加(_标识的坐标(坐标,地址));
如果(_addressed.length>1){
最终可拼接多段线=
等待装配策略。构建路线(构建列表
.map((identifiedCoordinate)=>identifiedCoordinate.address));
集合多段线.forEach(_route.add);
添加(_assembleMarkersUpdate());
}
result.close();
}().catchError(result.addError);
返回result.stream;
}
这样,程序逻辑独立于是否有人监听流而运行。您仍然需要缓冲所有流事件。没有真正的方法可以避免这种情况,除非您可以在以后计算它们,因为您不知道何时有人可能会侦听返回的流。它不必在返回时立即发生