简体   繁体   中英

Can't yield in forEachAsync inside Stream in dart/flutter

I have a forEachAsync inside an async* Stream and can't 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 .

I'm using the bloc pattern which reacts to the emited ProjectStates based on the current ProjectSelected event

Your attempt doesn't work because you're using yield in a callback , not in the function that's returning a 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:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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