DART / CHAPTER 12

Streams, ordering, and cancellation

Advanced

Treat asynchronous sequences as a separate contract from one result.

By the end of this chapter

  • Consume events with await for
  • Distinguish single-subscription and broadcast delivery
  • Define cleanup and cancellation behavior

The idea

A Future represents one eventual outcome, while a Stream represents asynchronous events over time. Await for processes events sequentially and can use ordinary try and catch around the consumption loop. A stream may emit errors as well as data. Decide whether a failure should stop processing, be reported, or be transformed instead of treating every stream like a finite list.

A single-subscription stream and a broadcast stream have different listener contracts. Broadcast delivery does not automatically replay old events to late listeners. Cancellation should release resources owned by a producer or subscription, but it does not undo work already completed. Keep event ordering and buffering assumptions explicit, especially when adding asynchronous transformations or connecting a fast producer to a slower consumer.

Dart example
Stream<int> counts() async* { yield 2; yield 5; }
Future<void> main() async {
  var total=0;
  await for (final n in counts()) { total+=n; }
  print(total);
}
Result
7

The loop waits for both ordered events and prints the aggregate after the stream completes.

Try it yourself

Consume a stream of records and stop once a required number of matching events has arrived.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Which abstraction naturally represents several asynchronous events over time?