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>
}Défi
FacileConstruisons 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 classeWeatherServicequi simule la récupération d'informations météo. Votre classe doit avoir :- Une méthode
fetchTemperature(String city)qui retourne unFuture<int>. UtilisezFuture.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 unFuture<String>. UtilisezFuture.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 unFuture<String>. Cette méthode doit attendre (await) à la foisfetchTemperatureetfetchCondition, puis retourner une chaîne formatée :'[city]: [temperature]C, [condition]'
- Une méthode
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!
- Créer une instance de
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!'
}
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
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository