简体   繁体   English

无法在 dart/flutter 中的 Stream 内的 forEachAsync 中屈服

[英]Can't yield in forEachAsync inside Stream in dart/flutter

I have a forEachAsync inside an async* Stream and can't yield .我在async* Stream有一个forEachAsync并且无法yield

Stream<ProjectState> _mapProjectSelectedEventToState(ProjectSelected event) async* {
    try {
      yield ProjectLoading(
        message: 'Fetching database',
        fetchedCount: 0,
        totalCount: 1,
      );
      await forEachAsync(fileModels, (FileEntity fileModel) async {
        await downloader.download(filename: fileModel.hashName);
        _totalMediaFilesFetched++;

        //// ERROR - THIS DOES NOT WORK ////
        yield (ProjectLoadingTick(
          _totalMediaFiles,
          _totalMediaFilesFetched,
        ));

      }, maxTasks: 5);
    } catch (error, stacktrace) {
      yield ProjectFailure(error: error);
    }
  }

I've tried other means by dispatching the message and converting it to a state but it doesn't work as well.我尝试了其他方法,即发送消息并将其转换为状态,但效果不佳。 It seems like the whole app is blocked by this await forEachAsync .似乎整个应用程序都被这个await forEachAsync阻止了。

I'm using the bloc pattern which reacts to the emited ProjectStates based on the current ProjectSelected event我正在使用 bloc 模式,它根据当前的ProjectSelected event对发出的ProjectStates做出反应

Your attempt doesn't work because you're using yield in a callback , not in the function that's returning a Stream .您的尝试不起作用,因为您在callback 中使用了yield ,而不是在返回Stream的函数中。 That is, you're attempting the equivalent of:也就是说,您正在尝试等效于:

Stream<ProjectState> _mapProjectSelectedEventToState(ProjectSelected event) async* {
  ...
  await forEachAsync(fileModels, helperFunction);
  ...
}

Future helperFunction(FileEntity fileModel) async {
  ...
  yield ProjectLoadingTick(...);
}

which doesn't make sense.这没有意义。

Since care about forEachAsync 's ability to set a maximum limit to the number of outstanding asynchronous operations, you might be better off using a StreamController that you can manually add events to:由于关心forEachAsync为未完成的异步操作的数量设置最大限制的能力,您最好使用StreamController ,您可以手动将事件添加到:

var controller = StreamController<ProjectState>();

// Note that this is not `await`ed.
forEachAsync(fileModels, (FileEntity fileModel) async {
    await downloader.download(filename: fileModel.hashName);
    _totalMediaFilesFetched++;

    controller.add(ProjectLoadingTick(
      _totalMediaFiles,
      _totalMediaFilesFetched,
    ));
  },
  maxTasks: 5);
yield* controller.stream;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM