首页 > 解决方案 > 有没有办法防止必须等待返回流的异步方法?

问题描述

我们目前有一个返回 a 的方法,Future<Stream<Position>>因为在内部我们必须等待返回 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;
}

所以这里发生的是:

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

我觉得我们也可以在不执行 await 并返回Future. 类似于以下内容:

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

不知何故,这似乎是可能的,但也包括管理流的一些开销,并确保它在插件的实时周期期间关闭并正确清理,或者当用户取消订阅时将事件传递给_eventChannel等。

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

标签: asynchronousstreamasync-awaitdart

解决方案


您可以将代码编写为async*函数,该函数将返回 aStream并且仍然允许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);
  }
}

或者,如果您使用的是非async函数,您也可以使用StreamCompleterfrom package:async。它允许您现在返回Stream,即使您稍后才获得真正的流。当这种情况发生时,你StreamCompleter用真实的流“完成”,原始流的行为就好像它是真实的流一样。


推荐阅读