dart-lang / stream_transform

Dart utility methods to create StreamTransfomer instances to manipulate Streams

Home Page:https://pub.dev/packages/stream_transform

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implement asyncSwitchMap

xzhorikx opened this issue · comments

If would be handy to have something like asyncSwitchMap in this package.

Use case
Creation of the child stream requires asynchronous code execution.

Example:
Loading user's items from the database. UI must react on changes in both user info stream and item info stream.

/// Provider interface for database
abstract class Provider {
  Furure<T> provide();
}
/// Abstract database class
abstract class Database {
  Stream<UserItem> findByUserId(String userId);
}
/// Item repository
class ItemRepository {
  ...
  Stream<UserItem> findByUserId(Stream<User> userStream) {
    userStream
      .swtichMap((User user){
        /// Database needs to be accessed with `await` keyword. Currently it is not possible to achieve this syntax with switchMap()
        Database db = await _databaseProvider.provide();
        return db.findbyUserId(user.id);
      });
  }
}

If this implementation is possible, it would be really nice to have it in order to make code cleaner.

If you have a Future<Stream> you can convert to a Stream with StreamCompleter.fromFuture. https://pub.dev/documentation/async/latest/async/StreamCompleter/fromFuture.html

The behavior difference depends on whether you hope for the output stream to wait to start listening on the subsequent stream until after the Future has completed, while still emitting events from the previous one. That behavior isn't possible today with StreamCompleter and switchLatest or switchMap, but from what I can tell I don't think you'd want that behavior. (I'm also curious why findByUserId returns a Stream instead of a Future, but that's unrelated to the immediate problem).

class ItemRepository {
  Stream<UserItem> findByUserId(Stream<User> userStream) {
    userStream
        .map((user) async {
          final db = await _databaseProvider.provide();
          return db.findbyUserId(user.id);
        })
        .map(StreamCompleter.fromFuture)
        .switchLatest();
  }
}