3 votes

Créer un nouveau flux à partir d'un flux dans Dart

Je soupçonne que ma compréhension de la Stream à Dart pourrait présenter quelques lacunes...

J'ai une situation dans laquelle j'aimerais qu'une application Dart réponde à des entrées intermittentes (ce qui suggère immédiatement l'utilisation de Streams ou Future peut-être). Je peux mettre en œuvre le comportement que je souhaite avec auditeur mais je me demandais comment le faire d'une manière plus efficace et plus Dart. esque manière.

À titre d'exemple simple, le programme suivant (fonctionnel) écoute les saisies clavier de l'utilisateur et ajoute au document un élément div contenant ce qui a été tapé depuis l'espace précédent, chaque fois que la barre d'espacement est actionnée.

import  'dart:html';

main() {
  listenForSpaces(showInput);
}

void  listenForSpaces(void  Function(String) listener) {
  var input =  List<String>();
  document.onKeyDown.listen((keyboardEvent) {
    var key = keyboardEvent.key;
    if (key ==  " ") {
      listener(input.join());
      input.clear();
    } else {
      input.add(key.length >  1  ?  "[$key]"  : key);
    }
  });
}

void  showInput(String message) {
  document.body.children.add(DivElement()..text = message);
}

Ce que j'aimerais pouvoir faire, c'est créer un nouveau fichier Stream de la Stream que j'écoute (dans l'exemple ci-dessus, pour créer un nouveau fichier Stream de onKeyDown ). En d'autres termes, je pourrais définir le programme ci-dessus comme suit :

var myStream = ...
myStream.listen(showInput);

Je soupçonne qu'il existe un moyen de créer un Stream et ensuite, à différents moments et endroits, y insérer des éléments ou lui demander d'émettre une valeur : j'ai l'impression de passer à côté de quelque chose de simple. En tout état de cause, toute aide ou orientation vers une documentation serait appréciée.

4voto

lrn Points 8630

La création d'un nouveau flux à partir d'un flux existant est assez facile avec une fonction async* fonction. Pour un flux normal, je ferais simplement :

Stream<String> listenForSpaces() async* {
  var input = <String>[];
  await for (var keyboardEvent in document.onKeyDown) {
    var key = keyboardEvent.key;
    if (key == " ") {
      yield input.join();
      input.clear();
    } else {
      input.add(key.length > 1 ? "[$key]" : key);
    }
  }
}

En async* propage les pauses dans le flux sous-jacent et peut éventuellement mettre la source en pause pendant la fonction yield . Ce n'est pas forcément ce que vous voulez, car mettre en pause un flux d'événements DOM peut vous faire manquer des événements. Pour un flux DOM, je préférerais probablement utiliser la méthode StreamController ci-dessus.

1voto

Günter Zöchbauer Points 21340

Il existe plusieurs méthodes et un paquet complet rxdart pour permettre toutes sortes de choses.

Seul le consommateur final doit utiliser listen et seulement si vous souhaitez explicitement vous désinscrire, sinon utilisez forEach

Si vous voulez manipuler des événements comme dans votre exemple, utilisez map .

1voto

richthepanda Points 943

Je n'avais pas l'intention de répondre à ma propre question, mais j'ai trouvé une réponse très simple à cette question dans le site web de la Commission européenne. dartlang création de flux article ; au cas où il serait utile à d'autres :

Plus précisément, si nous souhaitons créer un flux dans lequel nous pouvons insérer des éléments à des moments et à des endroits arbitraires du code, nous pouvons le faire via la fonction Contrôleur de flux classe. Les instances de cette classe ont un add nous pouvons simplement utiliser la méthode stream comme notre flux.

A titre d'exemple, le code de ma question pourrait être réécrit comme suit :

import 'dart:html';
import 'dart:async';

main() async {
  // The desired implementation stated in the question:
  var myStream = listenForSpaces();
  myStream.listen(showInput);
}

Stream<String> listenForSpaces() {
  // Use the StreamController class.
  var controller = StreamController<String>();

  var input = List<String>();
  document.onKeyDown.listen((keyboardEvent) {
    var key = keyboardEvent.key;
    if (key == " ") {
      // Add items to the controller's stream.
      controller.add(input.join());
      input.clear();
    } else {
      input.add(key.length > 1 ? "[$key]" : key);
    }
  });

  // Listen to the controller's stream.
  return controller.stream;
}

void showInput(String message) {
  document.body.children.add(DivElement()..text = message);
}

(Comme indiqué dans l'article, nous devons être prudents si nous voulons créer un flux à partir de zéro de cette manière, car rien ne nous empêche d'insérer des éléments dans des flux qui n'ont pas d'abonnés actifs associés ; les éléments insérés seraient dans ce cas mis en mémoire tampon, ce qui pourrait entraîner une fuite de mémoire).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X