dart:async propose les fonctionnalités centrales de la programmation asynchrone Dart : Future, Stream.
- L’utilisation de
Future / Streamne nécessite pas forcément d’importer manuellement dart:async, car dart:core l’exporte déjà ;- Si vous voulez utiliser des types comme
StreamController,StreamSubscription,ParallelWaitError, vous devez réaliser un import explicite :
import 'dart:async';Langage du code : JavaScript (javascript)
Deux concepts fondamentaux :
- Future : représente un résultat asynchrone unique (une seule valeur ou une seule erreur produite à un moment ultérieur)
- Stream : représente une série continue de données asynchrones (produit plusieurs valeurs successivement, comparable à un flux d’événements)
Future
1. async / await
Méthode à privilégier, plus lisible que les appels chaînés .then()
- Toute fonction marquée
asyncrenvoie un Future ; awaitattend la fin du Future et suspend l’exécution du code courant jusqu’à réception du résultat ;- Utilisez
try-catchpour intercepter les exceptions asynchrones.
// async 函数返回 Future
Future<String> findEntryPoint() async => "main.dart";
Future<int> runExecutable(String entry, List args) async => 0;
Future<void> flushThenExit(int code) async {}
// await 写法(推荐)
Future<void> runUsingAsyncAwait() async {
try {
var entryPoint = await findEntryPoint();
var exitCode = await runExecutable(entryPoint, []);
await flushThenExit(exitCode);
} catch (e) {
// 统一捕获异常
print("出错:$e");
}
}Langage du code : JavaScript (javascript)
2. .then() / .catchError() : syntaxe chaînée traditionnelle
.then(): exécute un rappel quand le Future se termine avec succès ; renvoie un nouveau Future pour continuer la chaîne.catchError(): intercepte les erreurs ; doit être chaîné sur le retour de then, sinon les erreurs à l’intérieur du then ne seront pas capturées
void runUsingFuture() {
findEntryPoint()
.then((entryPoint) {
return runExecutable(entryPoint, []);
})
.then(flushThenExit)
.catchError((e) {
print("异常:$e");
});
}Langage du code : JavaScript (javascript)
3. Attendre plusieurs Futures exécutés en parallèle
① Future.wait()
Attend que toutes les tâches soient terminées ; si un seul Future échoue, l’ensemble échoue immédiatement
Future<void> task1() async {}
Future<void> task2() async {}
Future<void> task3() async {}
void testWait() async {
await Future.wait([
task1(),
task2(),
task3(),
]);
print("全部任务执行完成");
}Langage du code : JavaScript (javascript)
② List.wait / Record.wait (nouvelle fonctionnalité, gestion fine des erreurs concurrentes)
Lève une ParallelWaitError qui permet de distinguer quelles tâches ont réussi et lesquelles ont échoué, sans blocage mutuel.
Future<int> delete() async => 1;
Future<String> copy() async => "ok";
Future<bool> errorTask() async {
throw Exception("任务失败");
}
void main() async {
try {
// 列表形式
var results = await [delete(), copy(), errorTask()].wait;
} on ParallelWaitError<List<Object?>, List<AsyncError?>> catch (e) {
print(e.values); // 成功有值,失败为null
print(e.errors); // 成功为null,失败存放错误信息
}
// Record元组形式:支持不同类型Future
try {
final (resInt, resStr, resBool) = await (delete(), copy(), errorTask()).wait;
} on ParallelWaitError<(int?, String?, bool?), (AsyncError?, AsyncError?, AsyncError?)> catch(e) {
}
}Langage du code : JavaScript (javascript)
Stream
Un Stream représente un flux continu de données asynchrones (lecture ligne par ligne d’un fichier, événements de clic sur interface, flux de données réseau).
Deux modes d’utilisation
1 : await for boucle asynchrone (lisible, comparable à une itération synchrone)
Adapté aux flux de données finis ; déconseillé pour des flux d’événements infinis (clics d’interface), car il bloque le reste du code.
import 'dart:io';
Future<void> readFileByAwaitFor() async {
var file = File("config.txt");
Stream<List<int>> input = file.openRead();
var lines = input
.transform(utf8.decoder)
.transform(const LineSplitter());
try {
await for (final line in lines) {
print("读取一行:$line");
}
print("文件读取完毕");
} catch (e) {
print("读取异常 $e");
}
}Langage du code : PHP (php)
2 .listen() abonnement à l’écoute (adapté aux flux infinis)
inputStream.listen(
(data) {
// 收到数据回调
},
onError: (err) {
// 发生错误
},
onDone: () {
// 流正常关闭完成
},
);Langage du code : JavaScript (javascript)
listen renvoie un
StreamSubscriptionsur lequel vous pouvez appeler.cancel()pour annuler l’abonnement.
Méthodes courantes de manipulation de Stream
- Filtrage :
where() - Limitation :
take()、takeWhile() - Saut d’éléments :
skip()、skipWhile() - Récupération d’un seul élément :
first、last、single、firstWhere()
Transformation des données Stream avec transform()
Modifie le type des données du flux grâce à un transformateur (cas typique : convertir un flux binaire en chaîne de caractères)
var lines = inputStream
.transform(utf8.decoder) // List<int> → String
.transform(const LineSplitter()); // String → 逐行字符串Langage du code : JavaScript (javascript)
Conseil de choix : listen() vs await for
- Lecture de fichiers, flux de séquences finies →
await for - Événements d’interface, messages continus et autres flux infinis →
.listen() - Une fois démarré, await for attend indéfiniment la fin du flux ; un flux infini provoquera un blocage du programme
Bibliothèque dart:async