如何从使用Futures / async / await的流中正确产生收益?

时间:2019-07-01 06:08:07

标签: asynchronous flutter dart

我遇到了一个奇怪的问题,即如果我在flutter应用程序中从提供程序中获取*,该函数中的其余代码将无法完成。

我正在使用BLoC模式,因此我的_mapEventToState函数如下所示:

  Stream<WizardState> _mapJoiningCongregationToState(
      int identifier, int password) async* {
    _subscription?.cancel();
    _subscription= (_provider.doThings(
            id: identifier, password: password))
        .listen((progress) => {
              dispatch(Event(
                  progressMessage: progress.progressText))
            }, onError: (error){
              print(error);
            }, onDone: (){
              print('done joiining');
            });
  }

然后在提供者/服务中...这是第一次尝试。

final StreamController<Progress> _progressStream = StreamController<JoinCongregationProgress>();

 @override
  Stream<JoinCongregationProgress> doThings(
      {int id, int password}) async* {

        await Future.delayed(Duration(seconds:2));
_progressStream.add(JoinCongregationProgress(progressText: "kake1..."));
await Future.delayed(Duration(seconds:2));
_progressStream.add(JoinCongregationProgress(progressText: "kake5!!!..."));
yield* _progressStream.stream;
}

yield语句返回,但是仅在 之后两个函数都已完成。这对我来说是完全有意义的,显然,我不希望代码在等待“等待”完成之前会乱序完成,并以某种方式运行yield *。

不过,为了“订阅”该服务的进度,我需要将流交还给调用者,在UI上编写更新等。在我看来,这就像移动产量一样简单*到第一次等待之前。这样。

 final StreamController<Progress> _progressStream = StreamController<JoinCongregationProgress>();

     @override
      Stream<JoinCongregationProgress> doThings(
          {int id, int password}) async* {
            yield* _progressStream.stream;
            await Future.delayed(Duration(seconds:2));
    _progressStream.add(JoinCongregationProgress(progressText: "kake1..."));
    await Future.delayed(Duration(seconds:2));
    _progressStream.add(JoinCongregationProgress(progressText: "kake5!!!..."));

    }

但是,然后在以后的_progressStream.add调用中设置断点表明这些断点永远不会被调用。我一直坚持下去,知道这可能是什么吗?我知道这与我如何混合期货和股流有关。

1 个答案:

答案 0 :(得分:1)

yield*等待返回的流完成。

在这种情况下,您想立即返回一个流,然后将一些数据异步馈入该流。

其他是否有向事件流控制器添加事件的东西?如果没有,您应该能够做到:

@override
Stream<JoinCongregationProgress> doThings({int id, int password}) async* {
    await Future.delayed(Duration(seconds:2));
    yield JoinCongregationProgress(progressText: "kake1...");
    await Future.delayed(Duration(seconds:2));
    yield JoinCongregationProgress(progressText: "kake5!!!...");
}

不需要流控制器。

如果其他功能也添加到流控制器中,那么您确实需要它。然后,您必须将流创建分散到一个异步部分(该部分更新流控制器)和一个同步部分(返回流)中。也许:

final StreamController<Progress> _progressStream = StreamController<JoinCongregationProgress>();

@override
Stream<JoinCongregationProgress> doThings({int id, int password}) {
  () async {
    await Future.delayed(Duration(seconds:2));
    _progressStream.add(JoinCongregationProgress(progressText: "kake1..."));
    await Future.delayed(Duration(seconds:2));
    _progressStream.add(JoinCongregationProgress(progressText: "kake5!!!..."));
  }(); // Spin off async background task to update stream controller.
  return _progressStream.stream;
}