Dart Generator Functions
Why
For a sequence of values, When you need to produce each of them on demand, consider using a generator function. Dart supports both synchronous
and asynchronous
generators.
On demand
means generating next value when requested. The request action can refer to calling [Iterator
How
*sync
: A generator withIterable
as output.*async
: A generator withStream
as output.yield
: Drop a value to the ouput tunnel. The function pauses execution at each “yield” until next value is requested. It’s like return, but does not teminate the function. Also the function automatically pauses at a yield statement while the steam subscription is paused (or iterator is not longer called moveNext()).*yield
: Delegate to another generator, which means current geneartor stops until the delegated one stop producing values.
What
-
One of good use case for
Synchrnous Generators
is to calculate a sequence of values which are computation-heavy. Due to generator’s laziness nature, we can do this in a memory-efficient manner.void main() { // Create an instance of the generator function Iterable<int> numbers = generateNumbers(5); // Iterate over the generated numbers and print them for (int number in numbers) { print(number); } } // A synchronous generator function that generates numbers from 0 to n-1 Iterable<int> generateNumbers(int n) sync* { for (int i = 0; i < n; i++) { yield i; // Pause and return the current value of i } }
-
Asynchrnous Generators
enable use to wait during the process of delivering a value. It’s not that different from thesynchrnous
one. Remeber: The key takeaway islaziness
.import 'dart:async'; void main() async { // List of sensor IDs List<String> sensorIds = ['sensor1', 'sensor2', 'sensor3']; // Process data from all sensors await processSensorData(sensorIds); } // Simulate a sensor data stream with temperature readings Stream<int> simulateSensorData(String sensorId) async* { for (int i = 0; i < 10; i++) { await Future.delayed(Duration(seconds: 1)); // Simulate delay yield (20 + i); // Simulate a temperature reading } } Future<void> processSensorData(List<String> sensorIds) async { // Create a list of sensor data streams List<Stream<int>> streams = sensorIds.map(simulateSensorData).toList(); // Merge all sensor data streams into a single stream Stream<int> mergedStream = StreamGroup.merge(streams); // Process each sensor reading as it arrives await for (int reading in mergedStream) { print('Received sensor reading: $reading'); // Perform any necessary processing here } }