Bibliothèque dart:async

dart:async propose les fonctionnalités centrales de la programmation asynchrone Dart : Future, Stream.

  1. L’utilisation de Future / Stream ne nécessite pas forcément d’importer manuellement dart:async, car dart:core l’exporte déjà ;
  2. 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 async renvoie un Future ;
  • await attend la fin du Future et suspend l’exécution du code courant jusqu’à réception du résultat ;
  • Utilisez try-catch pour 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 StreamSubscription sur 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 : firstlastsinglefirstWhere()

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

  1. Lecture de fichiers, flux de séquences finies → await for
  2. Événements d’interface, messages continus et autres flux infinis.listen()
  3. 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

Previous:

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *