What's the difference between async and async* in Dart?
Marking a function as async
or async*
allows it to use async
/await
keyword to use a Future
.
The difference between both is that async*
will always returns a Stream
and offer some syntax sugar to emit a value through yield
keyword.
We can therefore do the following:
Stream<int> foo() async* {
for (int i = 0; i < 42; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
This function emits a value every second, that increment every time
Short answer
async
gives you aFuture
async*
gives you aStream
.
async
You add the async
keyword to a function that does some work that might take a long time. It returns the result wrapped in a Future
.
Future<int> doSomeLongTask() async {
await Future.delayed(const Duration(seconds: 1));
return 42;
}
You can get that result by awaiting the Future:
main() async {
int result = await doSomeLongTask();
print(result); // prints '42' after waiting 1 second
}
async*
You add the async*
keyword to make a function that returns a bunch of future values one at a time. The results are wrapped in a Stream.
Stream<int> countForOneMinute() async* {
for (int i = 1; i <= 60; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
The technical term for this is asynchronous generator function. You use yield
to return a value instead of return
because you aren't leaving the function.
You can use await for
to wait for each value emitted by the Stream.
main() async {
await for (int i in countForOneMinute()) {
print(i); // prints 1 to 60, one integer per second
}
}
Going on
Watch these videos to learn more, especially the one on Generators:
- Isolates and Event Loops
- Futures
- Streams
- async / await
- Generators