Sujet vs comportementSubject vs ReplaySubject in Angular


124

J'ai cherché à comprendre ces 3:

Sujet , sujet du comportement et sujet de la relecture . Je voudrais les utiliser et savoir quand et pourquoi, quels sont les avantages de les utiliser et bien que j'aie lu la documentation, regardé des didacticiels et cherché sur Google, je n'ai pas réussi à comprendre cela.

Alors, quel est leur but? Un cas réel serait très apprécié car il n'a même pas besoin de coder.

Je préférerais une explication claire et pas seulement "a + b => c vous êtes abonné ...."

Je vous remercie


1
Il y a déjà une question de comportement sujet avec observable; stackoverflow.com/questions/39494058/… et la documentation sur le sujet de la relecture est claire imo github.com/Reactive-Extensions/RxJS/blob/master/doc/api/…
eko

Il y a une présentation relativement complète des sujets dans Rxjs dans cette réponse , qui complète bien la réponse de peeksilet. Cela comprend également des détails importants sur le comportement après la résiliation, il est donc bon de jeter un coup d'œil.
user3743222

Réponses:


278

Cela se résume vraiment au comportement et à la sémantique. Avec un

  • Subject- un abonné ne recevra que les valeurs publiées qui ont été émises après l'abonnement. Demandez-vous, c'est ce que vous voulez? L'abonné a-t-il besoin de connaître les valeurs précédentes? Sinon, vous pouvez l'utiliser, sinon choisissez l'un des autres. Par exemple, avec la communication composant à composant. Supposons que vous ayez un composant qui publie des événements pour d'autres composants en un clic. Vous pouvez utiliser un service avec un sujet pour communiquer.

  • BehaviorSubject- la dernière valeur est mise en cache. Un abonné recevra la dernière valeur lors de l'abonnement initial. La sémantique de ce sujet est de représenter une valeur qui change avec le temps. Par exemple, un utilisateur connecté. L'utilisateur initial peut être un utilisateur anonyme. Mais une fois qu'un utilisateur se connecte, la nouvelle valeur est l'état de l'utilisateur authentifié.

    Le BehaviorSubjectest initialisé avec une valeur initiale. Ceci est parfois important pour la préférence de codage. Disons par exemple que vous l'initialisez avec un null. Ensuite, dans votre abonnement, vous devez faire une vérification nulle. Peut-être OK, ou peut-être ennuyeux.

  • ReplaySubject- il peut mettre en cache jusqu'à un nombre spécifié d'émissions. Tous les abonnés recevront toutes les valeurs mises en cache lors de l'abonnement. Quand auriez-vous besoin de ce comportement? Honnêtement, je n'ai pas eu besoin d'un tel comportement, sauf dans le cas suivant:

    Si vous initialisez a ReplaySubjectavec une taille de tampon de 1, alors il se comporte exactement comme a BehaviorSubject. La dernière valeur est toujours mise en cache, elle agit donc comme une valeur changeant au fil du temps. Avec cela, il n'y a pas besoin de nullvérification comme dans le cas de l' BehaviorSubjectinitialisé avec un null. Dans ce cas, aucune valeur n'est jamais émise à l'abonné jusqu'à la première publication.

Donc, cela dépend vraiment du comportement que vous attendez (comme pour lequel utiliser). La plupart du temps, vous voudrez probablement utiliser a BehaviorSubjectparce que ce que vous voulez vraiment représenter, c'est cette sémantique «valeur dans le temps». Mais personnellement, je ne vois rien de mal à remplacer ReplaySubjectinitialisé par 1.

Ce que vous voulez éviter, c'est d'utiliser la vanille Subjectlorsque vous avez vraiment besoin d'un comportement de mise en cache. Prenez, par exemple, vous écrivez une garde de routage ou une résolution. Vous récupérez des données dans cette garde et les définissez dans un service Subject. Ensuite, dans le composant acheminé, vous vous abonnez au service sujet pour essayer d'obtenir cette valeur qui a été émise dans la garde. Oups. Où est la valeur? C'était déjà émis, DUH. Utilisez un sujet de "mise en cache"!

Voir également:


1
C'est court et facile à comprendre les différences. Lorsque la valeur change dans le service et que les composants changent également, la valeur est affichée, alors BehaviourSubjects ou Replay Subject est la solution.
Saiyaff Farouk

1
Je vous remercie! ReplaySubjectavec une taille de tampon de 1 était exactement ce dont j'avais besoin. J'avais un garde-route qui avait besoin de la valeur, mais il fallait attendre la première émission. Donc, un BehaviorSubjectne le coupait pas, car je ne voulais pas de valeur initiale ( nullne fonctionnerait pas non plus parce que je l'utilisais pour signifier un état)
menehune23

1
@ menehune23 J'avais également besoin de ReplaySubject pour une resolveclasse de garde angulaire . Mon service de données peut être asynchrone ou synchrone (si les données ont déjà été récupérées). S'il était synchrone, le Subject.next () était déclenché avant que la resolvefonction ne soit retournée et ne soit abonnée par Angular en interne. BehaviourSubject fonctionnerait peut-être, mais je devrais appeler explicitement complete()et ajouter également des nullvérifications pour la valeur initiale. Ce qui a fonctionné était nouveau ReplaySubject<DataType>(1) etresolveSubject.asObservable().take(1).map(....)
Drenai

1
J'utilise un ReplaySubject avec une taille de tampon de 1, mais pour une raison quelconque, lorsque j'obtiens un Observable avec .asObservable()l'Observable, j'envoie une valeur de nullaux abonnés avant d'appeler next()mon ReplaySubject. Je pensais qu'il n'était pas censé avoir une valeur initiale contrairement à BehaviorSubject?
Kyle V.

2
Je pense qu'un exemple assez simple que vous pourriez mentionner pour le sujet de la relecture serait pour un scénario de "chat" ou de lobby de jeu où vous voulez que les nouveaux participants voient les 10 derniers messages.
James le

16

Un résumé pratique des différents types observables, une dénomination non intuitive je sais lol .

  • Subject - Un abonné ne recevra les valeurs publiées qu'après la souscription.
  • BehaviorSubject - Les nouveaux abonnés obtiennent la dernière valeur publiée OU la valeur initiale dès la souscription.
  • ReplaySubject - Les nouveaux abonnés obtiennent toutes les valeurs précédemment publiées dès leur souscription

1-n valeurs publiées? Donc, s'il y avait 2 valeurs publiées, un ReplaySubject produirait -1 valeurs publiées ???
Jason Cheng le

@JasonCheng non il récupère toutes les valeurs précédemment publiées lors de l'abonnement, mettez à jour la réponse :)
Ricky Boyce

11
  1. Objet : Lors de l'abonnement, il obtient toujours les données qui sont poussées après son abonnement, c'est-à-dire que les valeurs précédentes ne sont pas reçues .
const mySubject = new Rx.Subject();

mySubject.next(1);

const subscription1 = mySubject.subscribe(x => {
  console.log('From subscription 1:', x);
});

mySubject.next(2);

const subscription2 = mySubject.subscribe(x => {
  console.log('From subscription 2:', x);
});

mySubject.next(3);

subscription1.unsubscribe();

mySubject.next(4);

Avec cet exemple, voici le résultat qui sera imprimé dans la console:

From subscription 1: 2
From subscription 1: 3
From subscription 2: 3
From subscription 2: 4

Notez que les abonnements qui arrivent en retard manquent certaines des données qui ont été introduites dans le sujet.

  1. Rejouer des sujets : peut aider en gardant un tampon des valeurs précédentes qui seront émises aux nouveaux abonnements.

Voici un exemple d'utilisation pour les sujets de relecture où un buffer of 2 previous valuesest conservé et émis sur les nouveaux abonnements:

const mySubject = new Rx.ReplaySubject(2);

mySubject.next(1);
mySubject.next(2);
mySubject.next(3);
mySubject.next(4);

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

Voici ce que cela nous donne sur la console:

From 1st sub: 3
From 1st sub: 4
From 1st sub: 5
From 2nd sub: 4
From 2nd sub: 5
  1. Sujets de comportement : sont similaires aux sujets de relecture, mais ne réémettent que la dernière valeur émise, ou une valeur par défaut si aucune valeur n'a été émise auparavant:
const mySubject = new Rx.BehaviorSubject('Hey now!');

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

Et le résultat:

From 1st sub: Hey now!
From 1st sub: 5
From 2nd sub: 5

Référence: https://alligator.io/rxjs/subjects/


4

De: Randall Koutnik livre «Créer des sites Web réactifs avec RxJS». :

Un sujet est un objet qui est un observable turbocompressé. À la base, un sujet agit un peu comme un observable régulier, mais chaque abonnement est relié à la même source. Les sujets sont également des observateurs et disposent de méthodes suivantes, erreurs et terminées pour envoyer des données à tous les abonnés à la fois. Parce que les sujets sont des observateurs, ils peuvent être transmis directement à un appel d'abonnement, et tous les événements de l'observable d'origine seront envoyés via le sujet à ses abonnés.

Nous pouvons utiliser le ReplaySubject pour suivre l'historique. UNE ReplaySubject enregistre les n derniers événements et les renvoie à chaque nouvel abonné. Par exemple dans l'application de chat. Nous pouvons l'utiliser pour suivre l'historique des discussions précédentes.

Un BehaviorSubject est une version simplifiée de ReplaySubject . Le ReplaySubject a stocké un nombre arbitraire d'événements, le BehaviorSubject n'enregistre que la valeur du dernier événement. Chaque fois qu'un BehaviorSubject enregistre un nouvel abonnement, il émet la dernière valeur à l'abonné ainsi que toutes les nouvelles valeurs transmises. Le BehaviorSubject est utile lorsqu'il s'agit d'unités d'état uniques, telles que les options de configuration.


1

La réponse la plus votée est manifestement erronée en affirmant que:

"Si vous initialisez a ReplaySubjectavec une taille de tampon de 1, il se comporte en fait comme un BehaviorSubject"


Ce n'est pas totalement vrai; Consultez cet excellent article de blog sur les différences entre ces deux éléments. Par exemple, si vous vous abonnez à un terminé BehaviorSubject, vous ne recevrez pas la dernière valeur mais pour un ReplaySubject(1)vous recevrez la dernière valeur.

C'est une différence importante à ne pas négliger:

const behavior = new BehaviorSubject(null);
const replay = new ReplaySubject(1);

behavior.skip(1).subscribe(v => console.log('BehaviorSubject:', v));
replay.subscribe(v => console.log('ReplaySubject:', v));

behavior.next(1);
behavior.next(2);
behavior.complete();
behavior.subscribe(v => console.log('Late B subscriber:', v));

replay.next(1);
replay.next(2);
replay.complete();
replay.subscribe(v => console.log('Late R subscriber:', v));

Consultez cet exemple de code ici qui provient d' un autre excellent article de blog sur le sujet.


0
     // ***********Subject  concept ***********
    let subject = new Subject<string>();


    subject.next("Eureka");
    subject.subscribe((data) => {
      console.log("Subscriber 1 got data >>>>> "+ data);
    });
    subject.subscribe((data) => {
      console.log("Subscriber 2 got data >>>>> "+ data);
    });

       // ********behaviour subject*********
    // Behavior subjects need a first value
let subject1 = new BehaviorSubject<string>("First value");


subject1.asObservable().subscribe((data) => {
  console.log("First subscriber got data behaviour subject>>>>> "+ data);
});
subject1.next("Second value")
  • Objet - Un abonné ne recevra les valeurs publiées qu'une fois l'abonnement effectué.
  • BehaviorSubject - Les nouveaux abonnés obtiennent la dernière valeur publiée OU la valeur initiale immédiatement après l'abonnement.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.