L’extension .Net Reactive offre aux développeurs un ensemble de fonctionnalités pour implémenter un modèle de programmation réactive pour les développeurs .Net afin de simplifier et rendre la gestion des événements plus expressive grâce à des actions déclaratives. Bien que les piliers clés de la mise à l’échelle réactive soient les interfaces IObserver et IObservable, en tant que développeur, vous n’avez souvent pas besoin d’implémenter ces interfaces vous-même. La bibliothèque prend en compte le type intégré Subject<T>, qui implémente des interfaces et prend en charge de nombreuses fonctions.
Les thèmes sont la base des différents sujets disponibles dans la bibliothèque, et il existe d’autres thèmes - <T>ReplaySubject,<T> BehaviourSubject et <T>AsyncSubject. Il est utile de comprendre les différences essentielles entre elles et comment les utiliser pour mieux utiliser la bibliothèque.
Dans cet article, nous allons comparer le Sujet<T> et son frère ou sœur, afin d’illustrer les différences entre leurs comportements.
Objet<T>
Comme mentionné précédemment, Subject<T> est la base des thèmes disponibles, offrant un moyen simple d’utiliser la bibliothèque sans avoir à implémenter<T> vous-même les interfaces IObservable et<T> IObserver. Une simple démonstration du type de thème est présentée ci-dessous.
Dans le code ci-dessus, nous avons créé une <T>instance de Subject, et puisqu’il implémente<T> IObserver et IObserverable<T>, nous utilisons la même instance pour vous abonner et publier la valeur sur IObserver. Un autre point important à noter ici est comment nous utilisons la surcharge de la méthode Subscribe pour accepter des actions en entrée. Cela sera fait pour chaque valeur publiée, dans ce cas en imprimant le numéro sur la console.
Essayons de montrer les valeurs publiées et celles que IObserver (dans cette action<T>) imprime à la console dans l’image suivante. Cela nous aidera à comparer facilement les autres frères et sœurs et variantes.
La première ligne représente la valeur publiée, et la seconde ligne représente la valeur reçue par l’IObserver. De plus, nous avons ajouté une ligne indiquant à quel moment l’observateur s’abonne au flux pendant l’exécution. Cette ligne est représentée par une ligne pointillée verticale.
Dans le code ci-dessus, nous avons remarqué que l’observateur s’était abonné au flux de données avant de publier la première valeur. L’image montre la ligne d’abonné placée avant le premier élément. Comme vous pouvez le voir sur la ligne de sortie, cela n’a aucun effet sur la sortie (à ce stade).
Mais que se passe-t-il si l’observateur ne s’inscrit aux données qu’après que certaines valeurs aient déjà été publiées ? Cela a-t-il un impact sur les données reçues par les observateurs ? Avant de regarder la sortie, écrivons d’abord le même code.
Dans le code ci-dessus, on peut observer que l’observateur ne s’achève au flux de données qu’après la publication de deux valeurs (1 et 2). Comme on pouvait s’y attendre, cela fera en sorte que les observateurs ne reçoivent pas les données publiées avant d’appeler la méthode d’abonnement. Comme montré dans la figure ci-dessous.
Que se passe-t-il si vous voulez lire toutes les valeurs publiées, même si l’observateur s’achève en retard ? C’est là que<T> ReplaySubject entre en jeu.
ReplaySubject<T>
ReplaySubject<T> met en cache les valeurs et les rejoue pour les abonnés ultérieurs. C’est utile pour éviter les conditions de course. Changeons le code précédent pour utiliser<T> ReplaySubject et voyons comment cela affecte ce que reçoit l’observateur.
Comme montré dans le code ci-dessus, il<T> <T>n’y a pratiquement aucun changement dans le code, sauf que nous utilisons désormais ReplaySubject au lieu de subject. Le diagramme suivant illustre l’impact sur les données reçues par l’observateur.
Comme montré sur l’image, la valeur mise en cache est désormais rejouée à l’abonné même si celui-ci s’abonne plus tard. Bien sûr, cette fonctionnalité utile a un prix. Cette implémentation mettra en cache chaque valeur publiée par l’abonné, ce qui peut causer des problèmes de mémoire lorsque la quantité de données est significativement plus importante.
Cependant,<T> ReplaySubject propose plusieurs solutions pour résoudre ce problème. Pour cet exemple, nous allons examiner deux exemples qui utiliseront des contraintes de taille et de temps pour limiter la valeur mise en cache.
Dans le premier cas, nous utiliserons la taille du cache pour limiter sa valeur. <T>Le constructeur de ReplaySubject fournit une surcharge, qui accepte un entier représentant la taille du tampon de cache (nombre maximal d’éléments). Dans notre exemple, changeons le code pour limiter la taille du cache à 1.
Notez comment nous utilisons <T>la surcharge du constructeur de ReplaySubject pour fournir la taille du cache comme 1. Cela limite la mise en cache et garantit qu’un seul élément est mis en cache et remplacé par un nouvel élément dès sa publication. L’impact de ce changement est présenté ci-dessous.
Une autre façon de limiter la mise en cache est de limiter le temps de l’élément mis en cache, ou en d’autres termes, de fournir un délai d’expiration pour cet élément mis en cache.
Écrivons du code pour illustrer cet exemple.
Comme pour le code précédent, nous utilisons<T> la surcharge du constructeur ReplaySubject pour spécifier le temps d’expiration des éléments dans le cache. Pour démontrer notre point de vue, nous avons introduit un délai entre la publication des valeurs.
Comme il faut 1200 ms complets avant que l’observateur ne s’abonne, tout élément dépassant le temps d’expiration de 1000 ms sera retiré du cache. Dans cet exemple, cela entraînera la suppression de la valeur 1 du cache et ne sera pas relue aux abonnés en retard. Comme montré dans la figure ci-dessous.
Il <T>existe d’autres surcharges pour ReplaySubject qui offrent plus de flexibilité et affinent les valeurs mises en cache, mais pour les exemples, nous conserverons les deux exemples déjà mentionnés ci-dessus.
ComportementSujet<T>
BehaviourSubject <T>est très similaire à<T> ReplaySubject en ce sens qu’il aide à mettre en cache les valeurs. Mais il y a une différence significative. BehaviourSubject<T> met en cache uniquement la dernière valeur publiée. Avant d’aller plus loin, écrivons un peu de code.
Si le BehaviorSubject<T> ne met en cache qu’une seule valeur (qui est la dernière connue), en quoi diffère-t-il d’un ReplaySubject de taille 1 <T>? Le diagramme suivant reflète clairement la situation du code ci-dessus.
Cependant, ce n’est pas entièrement vrai. Il y a deux différences importantes à comprendre ici. Le premier est la présence de défauts. Notez que dans le code ci-dessus, nous <T>fournissons la valeur 0 comme valeur par défaut dans le constructeur de BehaviourSubject. Si aucune valeur n’existe dans le cache (ou autrement dit, aucune donnée n’a été publiée avant l’abonnement de l’observateur), la valeur par défaut sera renvoyée. C’est différent de ReplaySubject, qui a une taille de 1<T>, et qui n’a aucune valeur. Le code suivant et une représentation visuelle de la séquence démontrent ce comportement.
La deuxième différence concerne le<T> comportement de BehaviorSubject et<T> ReplaySubject lorsqu’ils s’abonnent à une séquence complétée. Lorsque vous vous abonnez après l’achèvement, le BehaviorSubject <T> n’aura plus de valeur, comme indiqué dans le code ci-dessous.
Les abonnés sont garantis de ne recevoir aucune valeur car les abonnements ont lieu après la fin de la saison.
Cependant, <T>c’est le cas avec ReplaySubject. Il n’y a aucune garantie que l’observateur ne recevra aucune valeur, comme indiqué dans le code ci-dessous.
Comme indiqué dans le code ci-dessus, le cache a une taille et même si l’abonnement est appelé après la fin de l’appel, le cache restera (jusqu’à ce que la condition d’expiration soit remplie), donc dans ce cas, la dernière valeur publiée sera reçue.
AsyncSubject<T>
<T>AsyncSubject est le dernier frère du Sujet que nous allons explorer dans cet article<T>, et il est très similaire aux deux précédents (ReplaySubject et BehaviourSubject) en ce qu’il met également en cache les résultats. Mais encore une fois, il y a une différence significative. AsyncSubject ne publie la dernière valeur mise en cache que si la séquence est marquée comme complète <T> (il ne met en cache qu’une seule valeur, la dernière valeur).
Considérez le code suivant.
Cela générera une valeur pour l’observateur indiquant que la séquence est marquée comme la dernière valeur publiée avant l’achèvement - valeur 4. Comme montré dans la figure ci-dessous.
Mais que se passe-t-il si nous sautons l’appel qui marque la séquence comme complète ? Commentons la ligne et réessayons.
Cela ne génère aucune donnée pour l’observateur car AsyncSubject<T> ne publie les résultats qu’après que la séquence a été marquée comme complète.
C’est une différence significative à garder à l’esprit toute personne utilisant <T>AsyncSubject.
conclusion
Cet article illustre <T>les différences entre les différents frères et sœurs du Sujet ainsi que certaines de ses variantes. Il est souvent utile d’être conscient de ces différences subtiles, car elles peuvent manifester des comportements différents de ceux auxquels vous vous attendiez si vous ne vous en rendez pas compte.
Lien original :La connexion hyperlientérée est visible.
|