web-dev-qa-db-fra.com

Subject vs BehaviorSubject vs ReplaySubject dans Angular

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. Bien que j'aie lu la documentation, regardé les tutoriels et recherché sur Google, je n'ai rien compris à cela.

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

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

Je vous remercie

78
user6015054

Cela dépend vraiment du comportement et de la sémantique. Avec un

  • Subject - un abonné ne recevra que les valeurs publiées qui ont été émises après la souscription. Demandez-vous, est-ce ce que vous voulez? L'abonné a-t-il besoin de connaître les valeurs précédentes? Sinon, vous pouvez utiliser cette option, sinon choisissez-en une autre. Par exemple, avec une communication entre composants. Supposons que vous ayez un composant qui publie des événements pour d'autres composants en cliquant sur un bouton. 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 la souscription initiale. La sémantique de ce sujet doit 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 correspond à l'état de l'utilisateur authentifié.

    La BehaviorSubject est initialisée 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 effectuer un contrôle nul. Peut-être OK, ou peut-être ennuyeux.

  • ReplaySubject - il peut mettre en cache jusqu'à un nombre spécifié d'émissions. Tous les abonnés obtiendront toutes les valeurs 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, à l'exception du cas suivant:

    Si vous initialisez un ReplaySubject avec une taille de mémoire tampon de 1, alors il se comporte exactement comme un BehaviorSubject . La dernière valeur est toujours mise en cache, elle agit donc comme une valeur évoluant dans le temps. Avec cela, il n’est pas nécessaire de vérifier null comme dans le cas de BehaviorSubject initialisé avec un null, car aucune valeur n’est émise pour l’abonné avant la première publication.

Le comportement que vous attendez ainsi que celui à utiliser dépendent donc vraiment. La plupart du temps, vous voudrez probablement utiliser un BehaviorSubject parce que ce que vous voulez vraiment représenter est la sémantique "valeur sur le temps". Mais personnellement, je ne vois rien de mal à la substitution de ReplaySubject initialisée avec 1.

Ce que vous voulez éviter , c'est d'utiliser Vanilla Subject lorsque vous avez vraiment besoin d'un comportement de mise en cache. Prenez par exemple vous écrivez un 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 routé, vous vous abonnez à la fonction de service pour essayer d'obtenir la valeur émise dans la garde. Oops. où est la valeur? C'était déjà émis, DUH. Utilisez un sujet de "mise en cache"!

Voir également:

183
Paul Samsotha

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

  • Subject - Un abonné ne recevra les valeurs publiées qu'après sa souscription.
  • BehaviorSubject - Les nouveaux abonnés obtiennent la dernière valeur publiée OR la valeur initiale immédiatement après l'abonnement.
  • ReplaySubject - Les nouveaux abonnés obtiennent la dernière 1-n valeur (s) publiée (s) immédiatement après la souscription (uniquement si elle a déjà été émise).
5
Ricky Boyce

Du livre de Randall Koutnik "Construisez des sites Web réactifs avec RxJS.":

A Subject est un objet qui est un observable turbocompressé. À la base, un Subject agit un peu comme un observable régulier, mais chaque abonnement est relié à la même source. Sujets sont également des observateurs et ont des méthodes next, error et done pour envoyer des données à tous les abonnés à la fois. Parce que sujets sont des observateurs, ils peuvent être directement transmis à un appel d’abonnement et tous les événements de l’observable d’origine seront envoyés à ses abonnés par l’intermédiaire du sujet.

Nous pouvons utiliser le ReplaySubject pour suivre l’historique. A 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 de la discussion précédente.

A BehaviorSubject est une version simplifiée de ReplaySubject. Le ReplaySubject enregistre un nombre arbitraire d'événements, le BehaviorSubject enregistre uniquement la valeur du dernier événement. Chaque fois qu'un BehaviorSubject enregistre un nouvel abonnement, il envoie la dernière valeur à l'abonné ainsi que toutes les nouvelles valeurs transmises. Le BehaviorSubject est utile pour traiter avec des unités individuelles. d'état, tels que les options de configuration.

2
H S Progr
     // ***********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")
  • Sujet - Un abonné ne recevra que les valeurs publiées après l'abonnement.
  • BehaviorSubject - Les nouveaux abonnés obtiennent la dernière valeur publiée OR la valeur initiale immédiatement après l'abonnement.
0
user8199162
  1. Subject : lors de son abonnement, il obtient toujours les données qui sont envoyées après son abonnement, c'est-à-dire les valeurs poussées 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 à imprimer 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 transférées dans le sujet.

  1. Rejouer les sujets : peut aider en gardant un tampon des valeurs précédentes qui sera émis pour les nouveaux abonnements.

Voici un exemple d'utilisation pour les sujets de relecture dans lesquels un buffer of 2 previous values est 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 à la console:

From 1st sub: 3
From 1st sub: 4
From 1st sub: 5
From 2nd sub: 4
From 2nd sub: 5
  1. Sujets comportementaux : ressemblent aux sujets rediffusés mais ne réémettent que la dernière valeur émise, ou une valeur par défaut si aucune valeur n'a encore été émise:
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/

0
Varun Sukheja