Menu
Coddy logo textTech

Futures & async/await

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 76 sur 110.

Dans les applications réelles, de nombreuses opérations prennent du temps - récupérer des données depuis un serveur, lire des fichiers ou attendre une saisie de l'utilisateur. Dart gère cela avec Future, qui représente une valeur qui sera disponible à un moment donné dans le futur.

Un Future est comme une promesse : « Je vous donnerai le résultat quand il sera prêt. » Vous pouvez en créer un en utilisant Future.delayed() pour simuler une opération qui prend du temps :

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Pour travailler avec le résultat d'un Future, utilisez async et await. Marquez votre fonction comme async, puis utilisez await pour suspendre l'exécution jusqu'à ce que le Future se termine :

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Sans await, vous obtiendriez un Future<String> au lieu de la chaîne de caractères réelle. Le mot-clé await déballe le Future et vous donne la valeur à l'intérieur. Notez que toute fonction utilisant await doit être marquée async, et elle retourne automatiquement un Future.

Vous pouvez également renvoyer des valeurs directement depuis des fonctions asynchrones - Dart les enveloppe automatiquement dans un Future :

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Automatiquement enveloppé dans un Future<int>
}
challenge icon

Défi

Facile

Construisons un service météo qui simule la récupération de données météorologiques de différentes villes ! Vous allez vous entraîner à utiliser Future, async, et await pour gérer des opérations qui prennent du temps à s'exécuter.

Vous organiserez votre code en deux fichiers :

  • weather_service.dart : Créez une classe WeatherService qui simule la récupération d'informations météo. Votre classe doit avoir :
    • Une méthode fetchTemperature(String city) qui retourne un Future<int>. Utilisez Future.delayed() avec une durée de 100 millisecondes pour simuler un délai réseau. La méthode doit retourner une température basée sur le nom de la ville : retournez la longueur du nom de la ville multipliée par 3.
    • Une méthode fetchCondition(String city) qui retourne un Future<String>. Utilisez Future.delayed() avec un délai de 100 millisecondes. Retournez 'Sunny' si le nom de la ville a un nombre pair de caractères, sinon retournez 'Cloudy'.
    • Une méthode asynchrone getFullReport(String city) qui retourne un Future<String>. Cette méthode doit attendre (await) à la fois fetchTemperature et fetchCondition, puis retourner une chaîne formatée : '[city]: [temperature]C, [condition]'
  • main.dart : Importez votre service météo et démontrez comment fonctionnent les opérations asynchrones. Votre fonction main doit être async et :
    • Créer une instance de WeatherService
    • Afficher Fetching weather data...
    • Attendre et afficher le rapport complet pour 'Paris'
    • Attendre et afficher le rapport complet pour 'Tokyo'
    • Attendre et afficher le rapport complet pour 'London'
    • Afficher Done!

Remarquez comment chaque appel à getFullReport attend que la température et la condition soient récupérées avant de retourner le résultat combiné. Le mot-clé await suspend l'exécution jusqu'à ce que chaque Future soit terminé !

Sortie attendue :

Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!

Aide-mémoire

Un Future représente une valeur qui sera disponible dans le futur. Il est utilisé pour des opérations qui prennent du temps, comme la récupération de données ou la lecture de fichiers.

Créez un Future en utilisant Future.delayed() :

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Utilisez async et await pour travailler avec les Futures. Marquez la fonction comme async et utilisez await pour mettre en pause l'exécution jusqu'à ce que le Future se termine :

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Le mot-clé await déballe le Future et vous donne la valeur réelle. Sans lui, vous obtiendriez un Future<String> au lieu de la chaîne de caractères.

Toute fonction utilisant await doit être marquée async et retourne automatiquement un Future.

Les valeurs de retour des fonctions asynchrones sont automatiquement enveloppées dans un Future :

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Automatiquement enveloppé dans Future<int>
}

Essayez vous-même

import 'weather_service.dart';

Future<void> main() async {
  // TODO: Créer une instance de WeatherService
  
  // TODO: Afficher 'Fetching weather data...'
  
  // TODO: Attendre et afficher le rapport complet pour 'Paris'
  
  // TODO: Attendre et afficher le rapport complet pour 'Tokyo'
  
  // TODO: Attendre et afficher le rapport complet pour 'London'
  
  // TODO: Afficher 'Done!'
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet