Idiomatic streams in Dart?

312 Views Asked by At

In playing with Dart, particularly the dart:io library, I've found myself doing weird things with Streams to allow multiple listeners.

For example, I want to emulate the handler-stack pattern found in a number of Node libraries (like Connect & Express). To do so, I need to be able to set up multiple listeners on the request (and response), which means producing a broadcast stream from the request.

This cannot be the only thing I pass around becuase it does not maintain the properties of the request object (such as the response).

handleRequest (HttpRequest request) {
  var stream = request.asBroadcastStream();
  // pass stream *and* request to the handlers
}

An example handler, showing the problem, might look like this:

log (HttpRequest request, Stream stream) {
  DateTime start = new DateTime.now();
  stream.listen(null,
    onDone: () {
      DateTime finish = new DateTime.now();
      print("${request.method} ${request.uri} -> ${request.response.statusCode} ${finish.difference(start).inMilliseconds}ms");
    });
}

What's the idiomatic way of doing this kind of thing? I don't want to force Dart to conform to my JavaScriptish way.

1

There are 1 best solutions below

2
On

The asBroadcastStream() method is one of the most abused methods of Streams. I have written an article on Streams, and I hope it will be published soon. In short: the lifetime of a single-subscription Stream is defined by its subscription, and asBroadcastStream() destroys the lifetime management of a Stream. It's a source for resource leaks.

If you want to inform other parts of your program of messages you get from a single-subscription stream it is probably the best to create a new BroadcastStream (independent from the single-subscription stream) where you post messages when they arrive from the single-subscription stream. If these need more information you should send it this way.

In other words: create a new StreamController.broadcast and share this one with interested parties. If you want, you can also extend Stream and provide more information this way. Keep the single-subscription stream for yourself and publish interesting information in the shared broadcast stream.

Single-subscription streams are designed to be consumed by one entity.

Edit: the article has been published here.