Search code examples
dartstreamdart-async

How to return a stream based on another stream's event


I want to return a stream based on another stream's value/event.

For example, if I have a 2 streams, stream1 and stream2, I want to create a function which returns as stream either stream2 or null, depending on the value of stream1. How can I do that?

I tried to map stream1 and based on the event to yield stream2, but it does not work. I also can't listen to stream1 and based on the event yield stream2.

Stream<Data1?> getStream1() async* {
  // yield stream1
}

Stream<Data2?> getStream2(dynamic value) async* {
  //yield stream2 based on value
}

Stream<Data2?> getStream12() async* {
  final stream1 = getStream1();
  // not working
  yield* stream1.map((event) => event == null ? null : getStream2(event.var));
  // I also tried await for, but it has a strange behaviour
  // if I listen to the stream after (it's inconsistent)
  await for (var event in stream1) {
    if (event == null) {
      yield null;
    } else {
      yield* getStream2(event.var);
    } 
  }
}

Is there any solution to this, preferable without any additional package dependencies like rxdart, just pure dart?


Solution

  • Looks like await for have to work...

    Can you try this?

    Stream<int> getStream1() async* {
      yield 1;
      await Future.delayed(Duration(seconds: 1));
      yield null;
      await Future.delayed(Duration(seconds: 1));
      yield 2;
      await Future.delayed(Duration(seconds: 1));
    }
    
    Stream<int> getStream2(dynamic value) async* {
      yield value;
      await Future.delayed(Duration(seconds: 1));
      yield value;
      await Future.delayed(Duration(seconds: 1));
    }
    
    Stream<int> getStream12() {
      return getStream1().asyncExpand(
        (event) => event == null ? Stream.value(null) : getStream2(event),
      );
    }
    
    void main() {
      getStream12().listen(print);
    }
    

    Output:

    1
    1
    null
    2
    2