有没有一种方法可以避免必须等待异步方法返回流?

Mau*_*kom 2 asynchronous stream async-await dart

当前,我们有一个返回Future<Stream<Position>>just 的方法,因为在内部,我们必须等待返回a的方法的结果,Future然后才能调用另一个返回Stream<Position>实际感兴趣的方法的代码。以下是代码:

Future<Stream<Position>> getPositionStream(
    [LocationOptions locationOptions = const LocationOptions()]) async {
  PermissionStatus permission = await _getLocationPermission();

  if (permission == PermissionStatus.granted) {
    if (_onPositionChanged == null) {
      _onPositionChanged = _eventChannel
          .receiveBroadcastStream(
              Codec.encodeLocationOptions(locationOptions))
          .map<Position>(
              (element) => Position._fromMap(element.cast<String, double>()));
    }

    return _onPositionChanged;
  } else {
    _handleInvalidPermissions(permission);
  }

  return null;
}
Run Code Online (Sandbox Code Playgroud)

因此,这里发生的是:

  1. 我们正在等待该_getLocationPermission()方法,以便我们可以测试用户是否授予我们访问其设备(Android或iOS)上的位置服务的权限;
  2. 如果用户授予我们许可,我们将返回,Stream<Position>该值将在设备每次注册位置更改时更新。

我有一种感觉,我们也可以不用等待就返回一个Future。类似于以下内容:

  1. 手动创建并返回Stream<Position>该类的实例;
  2. 处理检查权限并_eventChannel.receiveBroadcastStreamthen()方法Future<PermissionStatus>返回的方法中调用的逻辑_getLocationPermission()(因此我们不必等待它);
  3. 将流_eventChannel.receiveBroadcastStream上发送的事件从中复制到先前创建(并返回)的流上。

某种程度上这似乎是可能的,但在管理流时还包括一些开销,并确保在插件的实时周期中或当用户取消订阅时将事件传递给事件_eventChannel等时,确保流已关闭并正确清理。

所以我想问题是,解决这种情况的最佳方法是什么?

lrn*_*lrn 5

您可以将代码编写为一个async*函数,该函数将返回a Stream并且仍然允许await在主体中:

Stream<Position> getPositionStream(
    [LocationOptions locationOptions = const LocationOptions()]) async* {
  PermissionStatus permission = await _getLocationPermission();

  if (permission == PermissionStatus.granted) {
    if (_onPositionChanged == null) {
      _onPositionChanged = _eventChannel
          .receiveBroadcastStream(
              Codec.encodeLocationOptions(locationOptions))
          .map<Position>(
              (element) => Position._fromMap(element.cast<String, double>()));
    }

    yield* _onPositionChanged;
  } else {
    _handleInvalidPermissions(permission);
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用的是非async功能,则也可以使用StreamCompleterfrom package:asyncStream即使您稍后仅获得实时流,它也允许您立即返回。发生这种情况时,您可以StreamCompleter用真实流“完成”操作,原始流的行为就好像是真实流一样。