Dart Lesson 32 – Async/Await | Dataplexa

Async and Await in Dart

In this lesson, you will learn about async and await in Dart. These keywords make working with Future objects easier, cleaner, and more readable.

Async and await are built on top of Futures, but they allow you to write asynchronous code that looks like synchronous code.


Why Async & Await Are Important

Without async and await, handling futures using then() can become complex and difficult to read when logic grows.

Async and await solve this problem by simplifying asynchronous workflows.


Basic Async Function

An async function always returns a Future.

Future fetchMessage() async {
  return "Hello from async function";
}

Using Await

The await keyword pauses execution until the future completes.

void main() async {
  String message = await fetchMessage();
  print(message);
}

Async with Delayed Operations

Let’s simulate a real-world API call using delay.

Future fetchUserAge() async {
  await Future.delayed(Duration(seconds: 2));
  return 28;
}

Consuming the Async Function

void main() async {
  print("Fetching age...");
  int age = await fetchUserAge();
  print("User Age: $age");
}

Execution Flow Explanation

  • The program starts immediately
  • Execution pauses at await
  • Resumes after the future completes

Async Function with Multiple Awaits

Async functions can await multiple futures in sequence.

Future fetchUserData() async {
  await Future.delayed(Duration(seconds: 1));
  String name = "Alex";

  await Future.delayed(Duration(seconds: 1));
  String city = "San Jose";

  return "$name from $city";
}

Using the Function

void main() async {
  String user = await fetchUserData();
  print(user);
}

Handling Errors with try-catch

Errors inside async functions are handled using try-catch.

Future divide(int a, int b) async {
  if (b == 0) {
    throw Exception("Division by zero");
  }
  return a ~/ b;
}

Error Handling Example

void main() async {
  try {
    int result = await divide(10, 0);
    print(result);
  } catch (e) {
    print("Error: $e");
  }
}

Async vs then()

Async/await improves:

  • Readability
  • Error handling
  • Maintainability

Async code looks cleaner and closer to natural logic flow.


Parallel Execution with Future.wait()

You can still combine async/await with Future.wait().

Future loadDashboard() async {
  var results = await Future.wait([
    Future.delayed(Duration(seconds: 2), () => "Profile Loaded"),
    Future.delayed(Duration(seconds: 1), () => "Settings Loaded"),
    Future.delayed(Duration(seconds: 3), () => "Messages Loaded"),
  ]);

  results.forEach(print);
}

Real-World Use Cases

  • API calls
  • Database queries
  • File reading and writing
  • User authentication

Common Mistakes

  • Using await outside async function
  • Forgetting error handling
  • Blocking logic inside async code

📝 Practice Exercises


Exercise 1

Create an async function that returns a username after a delay.

Exercise 2

Handle an error using try-catch.

Exercise 3

Use multiple await statements in a function.


✅ Practice Answers


Future getUsername() async {
  await Future.delayed(Duration(seconds: 2));
  return "dataplexa_user";
}

void main() async {
  try {
    String user = await getUsername();
    print(user);
  } catch (e) {
    print(e);
  }
}

What’s Next?

In the next lesson, you will learn about Streams in Dart, which handle multiple asynchronous values over time.