Short example of what I'm having trouble understanding:
Stream<int> getNumbersWithException() async* {
for (var i = 0; i < 10; i++) {
yield i;
if (i == 3) throw Exception();
}
}
With usage:
getNumbersWithException()
.handleError((x) => print('Exception caught for $x'))
.listen((event) {
print('Observed: $event');
});
This will stop at 3 with the output:
Observed: 0
Observed: 1
Observed: 2
Observed: 3
Exception caught for Exception: foo
From the documentation (https://dart.dev/tutorials/language/streams) and (https://api.dart.dev/stable/2.9.1/dart-async/Stream/handleError.html), this is as expected, as exceptions thrown will automatically close the stream.
- Does this mean that the correct way to handle exceptions in a stream, so that subscriptions can be long-lived in such an event, is to handle the exception inside the stream itself? That it is not possible to do so from the outside?
- Is this the same for broadcast streams?
- If I'm thinking about this in the wrong way, what are some pointers to start thinking right?
I'm currently thinking of streams as being a source of asynchronous data events that occasionally might be error events. From the documentation and examples, it all looks neat, but I'm thinking that wanting to handle errors and otherwise continue observing the data stream is a normal use case. I'm having a hard time writing the code to do so. But, I might be going about this wrong. Any insights will be much appreciated.
Edit: I can add that I've tried various things like using a stream transformer, with the same result:
var transformer = StreamTransformer<int, dynamic>.fromHandlers(
handleData: (data, sink) => sink.add(data),
handleError: (error, stackTrace, sink) =>
print('Exception caught for $error'),
handleDone: (sink) => sink.close(),
);
getNumbersWithException().transform(transformer).listen((data) {
print('Observed: $data');
});
Also, listen()
has an optional argument cancelOnError
that looks promising, but it defaults to false
, so no cigar here.