Dart Concurrency: Asynchronous programming

Dart Concurrency: Asynchronous programming

Streams

Streams in Dart represent sequences of asynchronous data or events. They provide a way to handle data as it becomes available, rather than waiting for all data to be present before processing it.


Using a Stream:

Using a Stream: Creating and using a Stream in Dart is straightforward. Here's a basic example:

import 'dart:async';

void main() {
  Stream<int> stream = Stream.fromIterable([1, 2, 3, 4, 5]);

  stream.listen((int value) {
    print(value);
  });
}

In this example, we create a Stream from an iterable and listen to its events using the listen() method.


Error Handling:

When working with streams, it's important to handle errors gracefully. Dart provides mechanisms for error handling in streams, such as the onError callback:

stream.listen((int value) {
  print(value);
}, onError: (error) {
  print('Error: $error');
});

This ensures that errors occurring during the stream processing are properly handled.


Cancelling a Stream:

In some cases, you may need to cancel a stream to stop listening to its events. Dart streams provide a cancel() method to achieve this:

StreamSubscription<int> subscription = stream.listen((int value) {
  print(value);
});

// Cancel the subscription after processing a certain number of events
// subscription.cancel();

By cancelling the subscription, you stop listening to further events emitted by the stream.


Transforming a Stream:

Dart streams can be transformed using various methods provided by the Stream class. For example, you can use map() to transform each event emitted by the stream:

stream.map((int value) => value * 2).listen((int doubledValue) {
  print(doubledValue);
});

This code doubles each value emitted by the stream before printing it.


Creating Streams from Scratch:

In addition to using existing streams, you can create streams from scratch in Dart. For example, you can use the Stream constructor to create a stream that emits a sequence of values over time:

Stream<int> countStream() async* {
  for (int i = 1; i <= 5; i++) {
    yield i;
    await Future.delayed(Duration(seconds: 1));
  }
}

This creates a stream that emits integers from 1 to 5 at one-second intervals.


Conclusion:

Dart Streams are a powerful mechanism for handling asynchronous data and events in Dart programming. By mastering the concepts of creating, using, error handling, cancelling, and transforming streams, developers can build responsive and efficient applications that can handle complex asynchronous scenarios with ease. As you continue to explore Dart, leveraging streams will unlock new possibilities for building reactive and event-driven applications across various domains.