What's the difference between async and async* in Dart?

DartFlutter

Dart Problem Overview


I am making an application using flutter framework . During this I came across with the keywords in Dart async and async*. Can anybody tell me what's the difference between them?

Dart Solutions


Solution 1 - Dart

Marking a function as async or async* allows it to use the async/await for a Future.

The difference between both is that async* will always return a Stream and offer some syntactical sugar to emit a value through the 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, which increments every time.

Solution 2 - Dart

Short answer

  • async gives you a Future
  • async* gives you a Stream.

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:

Solution 3 - Dart

Solution, Origins and Insights

This answer includes simplified and easy to understand examples

async

The async computation cannot provide a result immediately when it is started because the program may need to wait for an external response like:

  • Reading a file
  • Querying a database
  • Fetching data from an API

Instead of blocking all computation until the result is available, the asynchronous computation immediately returns a Future object which will eventually "complete" with the result.

Example (This type of async call can be used only without returning a response):

void main() async {
  // The next line awaits 5 seconds
  await Future.delayed(Duration(seconds: 5));
  // Pseudo API call that takes some time
  await fetchStocks();
}

Future

> A Future represents a computation that doesn’t complete immediately. Whereas a normal function returns the result, an asynchronous function returns a Future, which will > eventually contain the result. The Future will tell you when the result is ready.

  • Future is appended when the async function returns a value
  • Represents the result of a single computation (in contrast to a Stream)

Example:

Future<String> fetchUserOrder() =>
    // Imagine that this function is more complex and slow.
  Future.delayed(
    const Duration(seconds: 2),
        () => 'Large Latte',
  );

void main(List<String> arguments) async {
  var order = await fetchUserOrder(); 
  // App awaits 2 seconds
  print('Your $order is ready');
}

Stream

A source of asynchronous data events. A Stream provides a way to receive a sequence of events. Each event is either a data event, also called an element of the stream.

  • Stream is a sequence of results
  • From stream you get notified for results (stream elements)

async* (streams)

async* is an asynchronous generator that returns a Stream object. Made to create streams.

An example of using a stream and async*:

// Creating a new stream with async*
// Each iteration, this stream yields a number
Stream<int> createNumberStream(int number) async* {
  for (int i = 1; i <= number; i++) {
    yield i;
  }
}

void main(List<String> arguments) {
  // Calling the stream generation
  var stream = createNumberStream(5);
  // Listening to Stream yielding each number
  stream.listen((s) => print(s));
}

Result:

1
2
3
4
5

Bonus: Transforming an Existing Stream

If you already have a stream, you can transform it to a new stream based on the original stream’s events.

Example (same code as before but with a twist):

Stream<int> createNumberStream(int number) async* {
  for (int i = 1; i <= number; i++) {
    yield i;
  }
}

// This part is taking a previous stream through itself and outputs updated values
// This code multiplies each number from the stream
Stream<int> createNumberDoubling(Stream<int> chunk) async* {
  await for (final number in chunk) {
    yield number*2;
  }
}

void main(List<String> arguments) {
  // Here we are Transforming the first stream through createNumberDoubling stream generator
  var stream = createNumberDoubling(createNumberStream(5));
  stream.listen((s) => print(s));
}

Result:

2
4
6
8
10

Solution

The async and async* are close relatives, they are even from the same library dart:async The async represent a Future and a one-time exchange while the async* represents a Stream, a stream of multiple events

Solution 4 - Dart

Async functions execute synchronously until they reach the await keyword. Therefore, all synchronous code within an async function body executes immediately.

Future<int> foo() async {
  await Future.delayed(Duration(seconds: 1));
  return 0;
}

Async* is used to create a function that returns a bunch of future values one at a time. Each result is wrapped in a Stream.

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

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJagraj SinghView Question on Stackoverflow
Solution 1 - DartRémi RousseletView Answer on Stackoverflow
Solution 2 - DartSuragchView Answer on Stackoverflow
Solution 3 - DartStas SorokinView Answer on Stackoverflow
Solution 4 - Dartshirsh shuklaView Answer on Stackoverflow