Guides Pratiques

Annulation

Utiliser CancelToken pour interrompre coopérativement les fetchs en cours : lors de la navigation, d'un timeout ou d'une action utilisateur.

CancelToken est un signal d'annulation coopératif à usage unique. Le passer à fetchQuery, watchQuery ou prefetch et appeler cancel() pour interrompre le fetch avant son démarrage ou pendant son exécution.


Créer un token

main.dart
final token = CancelToken();

Un token ne peut être annulé qu'une seule fois. Appeler cancel() une deuxième fois est sans effet.


Annuler un fetchQuery

user_repository.dart
final token = CancelToken();

// Démarrer le fetch
final future = client.fetchQuery<User>(
  key: ['users', userId],
  fetcher: () => api.getUser(userId),
  cancelToken: token,
);

// L'annuler (ex. l'utilisateur a navigué ailleurs)
token.cancel();

try {
  final user = await future;
} on QoraCancelException catch (e) {
  // e.key est la clé de requête encodée en chaîne
  print('Fetch annulé : ${e.key}');
}

Quand annulé, fetchQuery lève QoraCancelException à l'appelant et restaure l'entrée de cache à son snapshot pré-fetch (aucun état partiel n'est laissé derrière).


Annuler un stream watchQuery

user_page.dart
final token = CancelToken();

final sub = client.watchQuery<User>(
  key: ['users', userId],
  fetcher: () => api.getUser(userId),
  cancelToken: token,
).listen((state) { ... });

// Au dispose du widget : annuler le fetch en cours
token.cancel();
await sub.cancel();
Annuler l'abonnement au stream est distinct de l'annulation du fetch. token.cancel() interrompt la requête HTTP ; sub.cancel() retire le listener d'état. Faire les deux au dispose pour un nettoyage propre.

Pattern de timeout

Combiner CancelToken avec Future.delayed pour implémenter un timeout de requête :

user_repository.dart
Future<User> fetchWithTimeout(int userId, Duration timeout) async {
  final token = CancelToken();

  Timer(timeout, token.cancel);

  try {
    return await client.fetchQuery<User>(
      key: ['users', userId],
      fetcher: () => api.getUser(userId),
      cancelToken: token,
    );
  } on QoraCancelException {
    throw TimeoutException('Fetch utilisateur expiré après $timeout');
  }
}

Annulation à la navigation dans Flutter

Dans un StatefulWidget, lier le token au cycle de vie du widget :

user_screen.dart
class _UserScreenState extends State<UserScreen> {
  CancelToken? _fetchToken;

  Future<void> _loadUser() async {
    _fetchToken = CancelToken();
    try {
      await context.qora.fetchQuery<User>(
        key: ['users', widget.userId],
        fetcher: () => api.getUser(widget.userId),
        cancelToken: _fetchToken,
      );
    } on QoraCancelException {
      // Widget disposé : ignorer
    }
  }

  @override
  void dispose() {
    _fetchToken?.cancel();
    super.dispose();
  }
}

API CancelToken

Constructeur

CancelToken()

Propriétés

PropriétéTypeDescription
isCancelledbooltrue après l'appel à cancel().

Méthodes

MéthodeSignatureDescription
cancel()voidMarque le token comme annulé. Idempotent et sûr à appeler plusieurs fois.

QoraCancelException

Levée par fetchQuery et prefetch quand un fetch est annulé via CancelToken.

class QoraCancelException implements Exception {
  final String key; // clé de requête normalisée encodée en JSON
}
PropriétéTypeDescription
keyStringLa clé de requête encodée en chaîne, ex. '["users",1]'

Hook du tracker

QoraTracker.onQueryCancelled(String key) est appelé chaque fois qu'un fetch est annulé via CancelToken. L'implémenter sur un tracker personnalisé pour journaliser ou mesurer les taux d'annulation :

analytics_tracker.dart
class AnalyticsTracker extends NoOpTracker {
  @override
  void onQueryCancelled(String key) {
    analytics.track('query_cancelled', {'key': key});
  }
}

Voir aussi

Copyright © 2026