← Flutter & Dart

Advanced Dart

What is a `Future` in Dart and how do `async` and `await` work?

Show answer — try answering out loud first

A Future represents a value that will be available later (an asynchronous operation, like a network request). async marks a function as asynchronous and makes it return a Future. await pauses the execution of that function until the Future resolves, without blocking the main thread.

Dart runs on a single thread. To avoid freezing the interface while it waits for something slow (network, disk), it uses asynchrony based on an event loop.

  • Future<T>: a promise of a value of type T that will arrive later. It can complete with a value or with an error.
  • async: marks the function. It automatically returns a Future.
  • await: inside an async function, it waits for a Future to finish and "unwraps" its value. While it waits, Dart keeps handling other things.

Alternative without await: .then() to chain and .catchError() for errors. With async/await the code reads as if it were synchronous, which is usually clearer.

// Simulates fetching data that takes time
Future<String> getUser() async {
  await Future.delayed(Duration(seconds: 1)); // simulates the wait
  return "Mike";
}

Future<void> main() async {
  print("Fetching user...");

  // With async/await
  final user = await getUser();
  print("Hello, $user");

  // Error handling with try/catch
  try {
    final data = await Future<int>.error("something failed");
    print(data);
  } catch (e) {
    print("Caught error: $e");
  }

  // Version with .then() (same result, different syntax)
  getUser().then((u) => print("With then: $u"));
}

Approximate output:

Fetching user...
Hello, Mike
Caught error: something failed
With then: Mike

Forgetting the await and working with the Future instead of its value. If you write final user = getUser(); (without await), user is a Future<String>, not the String. When you print it you'll see something like Instance of 'Future<String>'. Another mistake: using await outside an async function (it won't compile).

"A Future is a value that will be available later, typical of slow operations like a network call. Since Dart is single-threaded, I use asynchrony to avoid freezing the UI. I mark the function with async so it returns a Future, and I use await to wait for its result without blocking the thread; while it waits, the event loop handles other tasks. I handle errors with try/catch. The alternative is .then(), but async/await makes the code read as synchronous."

Quick challenge

What does this code print, and why?

Future<void> main() async {
  print("A");
  Future(() => print("B"));
  await Future.delayed(Duration.zero, () => print("C"));
  print("D");
}
See answer

It prints A, C, B, D... almost. In reality the typical order is A, then B and C get scheduled in the event queue. Since both are regular Futures, they go to the event queue in the order they were scheduled: B first, then C. But await in main pauses until its Future finishes. Usual result: A, B, C, D. The key thing to explain: print("A") is synchronous and comes out first; the rest are asynchronous tasks that run when the main thread is free, respecting the order of the queue.