What are generators in Dart (sync* and async*) and how do they work?
sobes.tech AI
Answer from AI
Generators in Dart are functions that return a sequence of values as they are generated, rather than all at once. The keywords sync* are used for synchronous generators and async* for asynchronous generators.
Synchronous generators (sync*)
Return an object of type Iterable. Use the keyword yield to produce the next value. The execution flow pauses until the next value is requested (for example, in a for-in loop).
Iterable<int> countUpTo(int max) sync* {
for (int i = 1; i <= max; i++) {
yield i; // Yield value
}
}
Asynchronous generators (async*)
Return an object of type Stream. Use the keyword yield to produce the next value. Also, yield* is used to yield all values from another Stream. The execution flow pauses and resumes upon new asynchronous events.
Stream<int> countUpToAsync(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(milliseconds: 100)); // Simulate async work
yield i; // Yield value
}
}
How they work:
When a generator function is called, its body does not execute immediately. An object (Iterable or Stream) is returned. The actual execution of the function body begins only when the first value is requested from the returned object. When the yield keyword is reached, the value is passed "outside," and the function's state is saved. The function's execution pauses. When the next value is requested, execution resumes from where it was paused, until the next yield or the end of the function.
Differences:
| Characteristic | sync* (Synchronous) | async* (Asynchronous) |
|---|---|---|
| Return type | Iterable |
Stream |
| Keywords | sync*, yield |
async*, yield, yield* |
Usage of await |
Not allowed | Allowed |
| Suspension | Until the next value is requested | Until the next asynchronous value appears |