web-dev-qa-db-fra.com

Futur / asynchrone / attendre à Dart

J'ai une fonction loadData qui charge du texte à partir d'un fichier:

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/data/entities.json');
}

La méthode loadString est issue du SDK Flutter et est asynchrone.

La méthode loadAsset est ensuite appelée dans une autre méthode, qui doit être marquée comme async, car loadAsset est asynchrone et je dois utiliser await:

Future<List<Entity>> loadEntities() async {
  String jsonData = await loadAsset();
  return parseData(jsonData);
}

La méthode parseData n'est pas asynchrone, elle reçoit un String, l'analyse et renvoie une liste d'objets:

List<Entity> parseData(String jsonString) {
  ...
}

Mais comme loadEntities doit être marqué avec async, cela nécessite qu'il retourne un Future, mais en pratique, ce n'est pas un Future car puisque j'utilise await, il attend la fin de la méthode loadAsset, puis appelle la fonction parseData en utilisant le résultat.

Cela se transforme facilement en un appel Snowball de async, car chaque méthode qui utilise loadEntities doit également être marquée comme async.

De plus, je ne peux pas utiliser loadEntities dans un constructeur de classe, car le constructeur doit être marqué comme async, ce qui n'est pas autorisé dans Dart.

Suis-je en utilisant le async/await motif dans Dart mal? Comment pourrais-je utiliser la méthode loadEntities dans un constructeur de classe?

16
RBasniak

Non, async est contagieux et il n'y a aucun moyen de revenir de l'exécution asynchrone à la synchronisation.

async/await n'est que du sucre syntaxique pour methodThatReturnsFuture().then(...)

Marquer une méthode avec async est uniquement pour vous permettre d'utiliser await à l'intérieur de son corps. Sans async, vous devrez toujours renvoyer un Future pour que le code appelant ne s'exécute qu'après que le résultat de loadAsset() sera disponible.

14
Günter Zöchbauer

Vous pouvez utiliser directement le Future renvoyé par l'appel asynchrone. Cela ressemblerait à quelque chose comme ceci:

class HasAsync {
  HasAsync() {
    asyncFunction().then((val) {
      print(val);
    });
  }

  Future<int> asyncFunction() async {
     int val = await otherFunction();
     return val;
  }
}

Vous ne pouvez tout simplement pas utiliser l'attente dans la fonction non asynchrone.

Comme vous l'avez marqué avec "flutter", je suppose que c'est dans une application flutter. Si c'est le cas, regardez les documents pour FutureBuilder - cela pourrait aider avec ce que vous essayez de faire.

9
rmtmckenzie