Range Over Channels in Dart

In a previous example, we saw how for and in provide iteration over basic data structures. We can also use this syntax to iterate over values received from a stream.

import 'dart:async';

void main() async {
  // We'll iterate over 2 values in the `queue` stream.
  final queue = StreamController<String>();
  queue.add("one");
  queue.add("two");
  queue.close();

  // This `await for` iterates over each element as it's
  // received from `queue`. Because we closed the
  // stream above, the iteration terminates after
  // receiving the 2 elements.
  await for (final elem in queue.stream) {
    print(elem);
  }
}

To run the program:

$ dart run range_over_streams.dart
one
two

This example also showed that it’s possible to close a non-empty stream but still have the remaining values be received.

In Dart, we use StreamController to create a stream and add elements to it. The await for loop is used to iterate over the stream, which is similar to the range loop in the original example. The close() method is called on the StreamController to close the stream, equivalent to closing the channel in the original code.

Dart’s streams are similar to channels in that they allow for asynchronous data flow, but they have some differences in usage and capabilities. The concept of ranging over a channel is represented in Dart by using await for on a stream.