# Futures and async/await — Dart

Source: https://www.skillbyai.com/en/dart/a-futures

> Write asynchronous code with Future, async, await and Future.wait.

## Waiting without blocking

Dart runs your code on a single thread per **isolate** with an **event loop**, so long-running work such as network requests, file I/O and timers is asynchronous. A **`Future<T>`** represents a value (or error) that will be available later. Mark a function **`async`** to use **`await`**, which pauses the function until the future completes without blocking the thread, so the UI stays responsive. Errors from awaited futures are thrown at the `await` and caught with ordinary `try`/`catch`. Run independent operations **concurrently** by starting them first and awaiting them together with **`Future.wait`** (or the record form `(f1, f2).wait`, which keeps each result's type). Add **timeouts** with `future.timeout(const Duration(seconds: 5))`. Common mistakes: forgetting `await` (the code continues before the work finishes, and errors go unhandled; the `unawaited_futures` lint catches this), and using `forEach` with an async callback, which does not wait; use `for` with `await` instead, or `Future.wait` for parallel work.

## The event loop

One thread processes events from queues; awaiting a future lets other events run in the meantime.

![A circular loop arrow around a single worker icon, fed by two queues of small event blocks.](assets/figures/dart/section-6-map.svg) — Figure 6.1 — Dart's event loop with event and microtask queues.

## Concurrent requests with Future.wait and records

Both calls run at the same time; types are preserved with the record form.

```dart
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<Map<String, dynamic>> getJson(Uri uri) async {
  final response = await http.get(uri).timeout(const Duration(seconds: 5));
  if (response.statusCode != 200) {
    throw http.ClientException('HTTP ${response.statusCode}', uri);
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}

Future<int> fetchStock(String sku) async => 10;   // stand-in for a real call

Future<void> loadProductPage(String id) async {
  final base = Uri.parse('https://api.example.com');
  try {
    final (product, stock) = await (
      getJson(base.resolve('products/$id')),
      fetchStock(id),
    ).wait;                                        // run concurrently, keep types
    print('${product['title']}: $stock in stock');
  } on http.ClientException catch (e) {
    print('Could not load product: ${e.message}');
  }
}

Future<void> main() async {
  await loadProductPage('pen-blue');
}
```

## Never forget await

A call like `saveOrder(order);` without `await` returns immediately, and any error it throws is reported as an unhandled exception later. Enable the `unawaited_futures` lint and use `unawaited(...)` from `dart:async` only for deliberate fire-and-forget work.

**Quiz:** How do you run two independent futures concurrently and wait for both?

- [ ] await each one in sequence
- [ ] Use forEach with async
- [x] Start both and await Future.wait (or the record .wait)
- [ ] Wrap them in a Stream

*Answer:* Start both and await Future.wait (or the record .wait). Starting both first and waiting together lets them run at the same time.
