dart-lang / web_socket_channel

StreamChannel wrappers for WebSockets.
https://pub.dev/packages/web_socket_channel
BSD 3-Clause "New" or "Revised" License
425 stars 112 forks source link

Sequential read issue #308

Open vd3d opened 11 months ago

vd3d commented 11 months ago

Hi,

I try to have a sequential read of every message, because I have a protocol to follow, it is in 3 steps:

And so I wish to:

Here is what I tried:

WebSocketChannel channel = WebSocketChannel.connect(Uri.parse(...));
dynamic connectionResponse = await channel.stream.last;
_handleStreamError(jsonDecode(connectionResponse));

String authPayload = '{"action": "auth", "key": "' + Secrets.alpaca.OAuthClientId + '", "secret": "' + Secrets.alpaca.OAuthClientSecret + '"}';
channel.sink.add(authPayload);
dynamic authResponse = await channel.stream.last;
_handleStreamError(jsonDecode(authResponse));

But I got an exception at the last 'channel.stream.last' : Unhandled Exception: Bad state: Stream has already been listened to

Any idea why, and how to manage this ?

Thanks

KammererTob commented 11 months ago

The underyling Stream of the WebSocketChannel is a single-subscription stream. Meaning it can only be listened to once. By using stream.last twice, you try to listen to it twice, which isn't allowed. Here is an excerpt from the documentation:

A single-subscription stream allows only a single listener during the whole lifetime of the stream. It doesn't start generating events until it has a listener, and it stops sending events when the listener is unsubscribed, even if the source of events could still provide more. The stream created by an async* function is a single-subscription stream, but each call to the function creates a new such stream.

Listening twice on a single-subscription stream is not allowed, even after the first subscription has been canceled.

https://api.flutter.dev/flutter/dart-async/Stream-class.html