2

I might be getting confused with dart streams and RX related frameworks here.

But just wanted to check, is it possible to map to a new async stream?

For example

apiService.signInStream returns Stream<signinResponse>

apiService.getUserDetailsStream returns Stream<userResponse>

So I want to make the sign in call, take the user id from it to get the user details.

I tried something like this...

apiService.signInStream(requestSignIn).asyncMap((event) => apiService.getUserDetailsStream(event.userId));

But that returns... Stream<Stream<userResponse>>

I'd like it to return <Stream<userResponse>

Do I have to listen within the map somehow?

Thanks

aidanmack
  • 518
  • 1
  • 5
  • 16

3 Answers3

0

You should listen:

apiService.signInStream(requestSignIn).listen((event) {
  apiService.getUserDetailsStream(event.userId)).listen((details) {
    // use event and details here
  });
});
Ber
  • 40,356
  • 16
  • 72
  • 88
  • Thats not ideal. If we make multiple api calls we end up with alot of nested listens. – aidanmack Dec 07 '22 at 13:20
  • @aidanmack Don't worry. This is the way streams work. It will not nest deeper than 2 levels. Assuming your `apiService.getUserDetailsStream` creates a stream per user. – Ber Dec 07 '22 at 13:32
0

There are many approaches and I cannot say which one you may use because I have no context of your project, all I have here are simply Streams.

Lets begin:

But that returns... Stream<Stream<userResponse>>

This is what return because this is what it is, you are iterating over a stream and returning another stream, streams are like lists, but asynchronous. Why do you want to ignore the userResponse stream? is this really a Stream? Why do not use a simply Future instead if you want just the returned data?

And since you're mapping the signInStream, I'll consider you:

  • Wanna map each signInStream event
  • Want just the first element of the getUserDetailsStream.

Run on DartPad: https://dartpad.dev/?id=17e2720be36c2bbde3da7d5a6381776d.

// What you have right now is:
final itIsWhatYouAreDoing = signInStream().asyncMap((event) => getUserDetailsStream());

// What you are saying you want to achieve:
final userDetailsStream = signInStream().asyncMap((event) async => await getUserDetailsStream().first);

print(itIsWhatYouAreDoing); // Stream<Stream<int>>
print(userDetailsStream); // Stream<int>

But this has some cons: you lose any other post-event emitted by all [getUserDetailsStream] Streams.

You didn't provide any detail about this, so I'll assuming they are irrelevant?!?

Alex Rintt
  • 1,618
  • 1
  • 11
  • 18
0

You can try this

apiService.signInStream(requestSignIn).asyncExpand((event) => 
    apiService.getUserDetailsStream(event.userId));

Remember to cancel the getUserDetailsStream otherwise your stream will be stuck waiting for getUserDetailsStream.

You can make use of takeWhile or take in dart to automatically kill the stream.

Moiz Sohail
  • 558
  • 5
  • 22