BehaviorSubject vs Observable?

Ik ben op zoek naar Angular RxJs-patronen en ik begrijp het verschil niet tussen een BehaviorSubjecten een Observable.

Voor zover ik weet, is een BehaviorSubjecteen waarde die in de loop van de tijd kan veranderen (er kan op worden geabonneerd en abonnees kunnen bijgewerkte resultaten ontvangen). Dit lijkt exact hetzelfde doel te zijn van een Observable.

Wanneer zou je een Observableversus een BehaviorSubjectgebruiken? Zijn er voordelen aan het gebruik van een BehaviorSubjectboven een Observableof omgekeerd?


Antwoord 1, autoriteit 100%

BehaviorSubjectis een type onderwerp, een onderwerp is een speciaal type waarneembaar, zodat u zich op berichten kunt abonneren zoals elk ander waarneembaar. De unieke kenmerken van BehaviourSubject zijn:

  • Het heeft een initiële waarde nodig omdat het altijd een waarde moet retourneren bij het abonnement, zelfs als het geen next()
  • heeft ontvangen

  • Bij inschrijving wordt de laatste waarde van het onderwerp geretourneerd. Een normale waarneembare wordt alleen geactiveerd wanneer deze een onnext
  • . ontvangt

  • u kunt op elk moment de laatste waarde van het onderwerp in een niet-waarneembare code ophalen met behulp van de getValue()-methode.

Unieke kenmerken van een onderwerp vergeleken met een waarneembare zijn:

  • Het is niet alleen een waarnemer, maar ook een waarnemer, dus je kunt naast het abonneren ook waarden naar een onderwerp sturen.

Bovendien kunt u een waarneembaar onderwerp van gedrag verkrijgen met behulp van de asObservable()-methode op BehaviorSubject.

Observableis een generiek, en BehaviorSubjectis technisch gezien een subtype van Observable omdat BehaviorSubject een waarneembare is met specifieke kwaliteiten.

Voorbeeld met BehaviorSubject:

// Behavior Subject
// a is an initial value. if there is a subscription 
// after this, it would get "a" value immediately
let bSubject = new BehaviorSubject("a"); 
bSubject.next("b");
bSubject.subscribe(value => {
  console.log("Subscription got", value); // Subscription got b, 
                                          // ^ This would not happen 
                                          // for a generic observable 
                                          // or generic subject by default
});
bSubject.next("c"); // Subscription got c
bSubject.next("d"); // Subscription got d

Voorbeeld 2 met regulier onderwerp:

// Regular Subject
let subject = new Subject(); 
subject.next("b");
subject.subscribe(value => {
  console.log("Subscription got", value); // Subscription wont get 
                                          // anything at this point
});
subject.next("c"); // Subscription got c
subject.next("d"); // Subscription got d

Een waarneembare kan worden gemaakt van zowel Subjectals BehaviorSubjectmet behulp van subject.asObservable().

Het enige verschil is dat je geen waarden naar een waarneembaar bestand kunt sturen met de next()-methode.

In Angular-services zou ik BehaviorSubjectgebruiken voor een gegevensservice, aangezien een hoekservice vaak wordt geïnitialiseerd voordat het onderdeel en het gedragssubject ervoor zorgen dat het onderdeel dat de service gebruikt de laatst bijgewerkte gegevens ontvangt, zelfs als er geen nieuwe updates sinds het abonnement van de component op deze gegevens.


Antwoord 2, autoriteit 19%

Waarneembaar: ander resultaat voor elke waarnemer

Een heel erg belangrijk verschil. Omdat Observable slechts een functie is, heeft het geen status, dus voor elke nieuwe Observer voert het de waarneembare create-code steeds opnieuw uit. Dit resulteert in:

De code wordt uitgevoerd voor elke waarnemer
. Als het een HTTP-aanroep is, wordt deze aangeroepen voor elke waarnemer

Dit veroorzaakt grote bugs en inefficiënties

BehaviorSubject (of Subject) slaat de details van de waarnemer op, voert de code slechts één keer uit en geeft het resultaat aan alle waarnemers.

Bijvoorbeeld:

JSBin: http://jsbin.com/qowulet/edit?js,console

// --- Observable ---
let randomNumGenerator1 = Rx.Observable.create(observer => {
   observer.next(Math.random());
});
let observer1 = randomNumGenerator1
      .subscribe(num => console.log('observer 1: '+ num));
let observer2 = randomNumGenerator1
      .subscribe(num => console.log('observer 2: '+ num));
// ------ BehaviorSubject/ Subject
let randomNumGenerator2 = new Rx.BehaviorSubject(0);
randomNumGenerator2.next(Math.random());
let observer1Subject = randomNumGenerator2
      .subscribe(num=> console.log('observer subject 1: '+ num));
let observer2Subject = randomNumGenerator2
      .subscribe(num=> console.log('observer subject 2: '+ num));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.min.js"></script>

Snippet uitvouwen


Antwoord 3, autoriteit 8%

Waarneembaaren onderwerpzijn beide waarneembare middelen die een waarnemer ze kan volgen. maar beide hebben een aantal unieke kenmerken. Verder zijn er in totaal 3 soorten onderwerpen die elk weer unieke kenmerken hebben. laten we proberen ze allemaal te begrijpen.

je kunt het praktische voorbeeld hier vinden op stackblitz.
(U moet de console controleren om de daadwerkelijke uitvoer te zien)

voer hier de afbeeldingsbeschrijving in

Observables

Ze zijn koud:Code wordt uitgevoerd wanneer ze ten minste één waarnemer hebben.

Maakt een kopie van gegevens:Observable maakt een kopie van de gegevens voor elke waarnemer.

Uni-directioneel:waarnemer kan geen waarde toekennen aan waarneembaar (oorsprong/master).

Subject

Ze zijn hot:code wordt uitgevoerd en waarde wordt uitgezonden, zelfs als er geen waarnemer is.

Gegevens delen:dezelfde gegevens worden gedeeld tussen alle waarnemers.

bidirectioneel:waarnemer kan waarde toekennen aan waarneembaar (oorsprong/master).

Als je het onderwerp gebruikt, mis je alle waarden die zijn uitgezonden voordat de waarnemer is gemaakt. Dus hier komt Onderwerp opnieuw afspelen

ReplaySubject

Ze zijn hot:code wordt uitgevoerd en waarde wordt uitgezonden, zelfs als er geen waarnemer is.

Gegevens delen:dezelfde gegevens worden gedeeld tussen alle waarnemers.

bidirectioneel:waarnemer kan waarde toekennen aan waarneembaar (oorsprong/master). plus

De berichtenstroom opnieuw afspelen:Het maakt niet uit wanneer u zich abonneert op het onderwerp van de herhaling, u ontvangt alle uitgezonden berichten.

Bij onderwerp en onderwerp opnieuw afspelen kunt u de beginwaarde niet instellen op waarneembaar. Dus hier komt Gedragsonderwerp

BehaviorSubject

Ze zijn hot:code wordt uitgevoerd en waarde wordt uitgezonden, zelfs als er geen waarnemer is.

Gegevens delen:dezelfde gegevens worden gedeeld tussen alle waarnemers.

bidirectioneel:waarnemer kan waarde toekennen aan waarneembaar (oorsprong/master). plus

De berichtenstroom opnieuw afspelen:Het maakt niet uit wanneer u zich abonneert op het onderwerp van de herhaling, u ontvangt alle uitgezonden berichten.

U kunt de beginwaarde instellen:u kunt het waarneembare initialiseren met de standaardwaarde.


Antwoord 4, autoriteit 3%

Het waarneembare object vertegenwoordigt een op push gebaseerde verzameling.

De Observer- en Observable-interfaces bieden een algemeen mechanisme voor push-gebaseerde meldingen, ook wel het Observer Design Pattern genoemd. Het Observable-object vertegenwoordigt het object dat meldingen verzendt (de provider); het Observer-object vertegenwoordigt de klasse die ze ontvangt (de waarnemer).

De Subject-klasse erft zowel Observable als Observer, in die zin dat het zowel een waarnemer als een waarneembaar is. U kunt een onderwerp gebruiken om alle waarnemers te abonneren en het onderwerp vervolgens abonneren op een backend-gegevensbron

var subject = new Rx.Subject();
var subscription = subject.subscribe(
    function (x) { console.log('onNext: ' + x); },
    function (e) { console.log('onError: ' + e.message); },
    function () { console.log('onCompleted'); });
subject.onNext(1);
// => onNext: 1
subject.onNext(2);
// => onNext: 2
subject.onCompleted();
// => onCompleted
subscription.dispose();

Meer over https://github.com/ Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md


Antwoord 5, autoriteit 2%

Eén ding dat ik in voorbeelden niet zie, is dat wanneer je BehaviorSubject cast naar Observable via asObservable, het gedrag overneemt van het retourneren van de laatste waarde bij abonnement.

Het is het lastige, omdat bibliotheken vaak velden als waarneembaar blootleggen (d.w.z. params in ActivatedRoute in Angular2), maar Subject of BehaviorSubject achter de schermen kunnen gebruiken. Wat ze gebruiken, zou van invloed zijn op het abonneergedrag.

Zie hier http://jsbin.com/ziquxapubo/edit?html,js, console

let A = new Rx.Subject();
let B = new Rx.BehaviorSubject(0);
A.next(1);
B.next(1);
A.asObservable().subscribe(n => console.log('A', n));
B.asObservable().subscribe(n => console.log('B', n));
A.next(2);
B.next(2);

Antwoord 6

Met een waarneembaarkun je je alleen abonneren terwijl een onderwerpstelt u in staat om zowel te publiceren als te abonneren.

Dus een onderwerp zorgt ervoor dat uw serviceszowel als uitgever als abonnee kunnen worden gebruikt.

Vanaf nu ben ik niet zo goed in Observable, dus ik zal alleen een voorbeeld van Subjectdelen.

Laten we het beter begrijpen met een Angular CLI-voorbeeld. Voer de onderstaande opdrachten uit:

npm install -g @angular/cli
ng new angular2-subject
cd angular2-subject
ng serve

Vervang de inhoud van app.component.htmldoor:

<div *ngIf="message">
  {{message}}
</div>
<app-home>
</app-home>

Voer de opdracht ng g c components/homeuit om de home-component te genereren. Vervang de inhoud van home.component.htmldoor:

<input type="text" placeholder="Enter message" #message>
<button type="button" (click)="setMessage(message)" >Send message</button>

#messageis hier de lokale variabele. Voeg een eigenschap message: string;
naar de klasse van app.component.ts.

Voer deze opdracht uit ng g s service/message. Dit genereert een service op src\app\service\message.service.ts. Lever deze service aan de app.

Importeer Subjectin MessageService. Voeg ook een onderwerp toe. De uiteindelijke code ziet er als volgt uit:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MessageService {
  public message = new Subject<string>();
  setMessage(value: string) {
    this.message.next(value); //it is publishing this value to all the subscribers that have already subscribed to this message
  }
}

Injecteer nu deze service in home.component.tsen geef een instantie ervan door aan de constructor. Doe dit ook voor app.component.ts. Gebruik deze service-instantie om de waarde van #messagedoor te geven aan de servicefunctie setMessage:

import { Component } from '@angular/core';
import { MessageService } from '../../service/message.service';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent {
  constructor(public messageService:MessageService) { }
  setMessage(event) {
    console.log(event.value);
    this.messageService.setMessage(event.value);
  }
}

Binnen app.component.tskunt u zich abonneren en afmelden (om geheugenlekken te voorkomen) voor het Subject:

import { Component, OnDestroy } from '@angular/core';
import { MessageService } from './service/message.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  message: string;
  subscription: Subscription;
  constructor(public messageService: MessageService) { }
  ngOnInit() {
    this.subscription = this.messageService.message.subscribe(
      (message) => {
        this.message = message;
      }
    );
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

Dat is het.

Nu wordt elke waarde die in #messagevan home.component.htmlwordt ingevoerd, afgedrukt in {{message}}in app.component.html


Antwoord 7

Denk aan Observablesals een pijp met stromend water erin, soms stroomt water en soms niet. In sommige gevallen heb je misschien een pijp nodig waar altijd water in zit. Je kunt dit doen door een speciale pijp te maken die altijd water bevat, hoe klein deze ook is, laten we deze speciale pijp BehaviorSubject, als u toevallig een watervoorzieningsleverancier in uw gemeenschap bent, kunt u ‘s nachts rustig slapen, wetende dat uw nieuw geïnstalleerde leiding gewoon werkt.

In technische termen: je kunt gebruiksgevallen tegenkomen waarbij een Observable altijd waarde zou moeten hebben, misschien wil je de waarde van een invoertekst in de loop van de tijd vastleggen, dan kun je een instantie van BehaviourSubject maken om dit soort gedrag te garanderen, laten we zeggen:


const firstNameChanges = new BehaviorSubject("<empty>");
// pass value changes.
firstNameChanges.next("Jon");
firstNameChanges.next("Arya");

Je kunt dan “waarde” gebruiken om veranderingen in de loop van de tijd te meten.


firstNameChanges.value;

Dit is handig wanneer je Observables later combineert, door te kijken naar het type van je stream als BehaviourSubject kun je er dan voor zorgen dat de stream minstens één keer afgaat of een signaal geeft.


Antwoord 8

app.component.ts

behaviourService.setName("behaviour");

behaviour.service.ts

private name = new BehaviorSubject("");
getName = this.name.asObservable();
constructor() {}
setName(data) {
    this.name.next(data);
}

custom.component.ts

behaviourService.subscribe(response=>{
    console.log(response);    //output: behaviour
});

Antwoord 9

Waarneembaar
is een Generiek,

Observables zijn luie verzamelingen van meerdere waarden in de loop van de tijd.

Is slechts een functie, geen status

Code-run voor elke waarnemer

BehaviorSubject:
Een Onderwerp dat een initiële waarde vereist en zijn huidige waarde doorgeeft aan nieuwe abonnees.

is technisch gezien een subtype van Observable omdat BehaviorSubject een observeerbaar is met specifieke kwaliteiten.

Heeft staat. Slaat gegevens op in het geheugen

Dezelfde code wordt slechts één keer uitgevoerd voor alle waarnemers

De unieke kenmerken van BehaviourSubject zijn de volgende:

Het heeft een initiële waarde nodig omdat het altijd een waarde moet retourneren bij het abonnement, zelfs als het geen next()

heeft ontvangen

Bij inschrijving wordt de laatste waarde van het onderwerp geretourneerd. Een normale waarneembare trigger wordt alleen geactiveerd wanneer deze een volgende

. ontvangt

u kunt op elk moment de laatste waarde van het onderwerp in een niet-waarneembare code ophalen met behulp van de getValue()-methode.


Antwoord 10

BehaviorSubjectvs Observable: RxJS heeft waarnemers en waarnemers, Rxjs biedt meerdere klassen om te gebruiken met gegevensstromen, en een daarvan is een BehaviourSubject.

Observables: Observables zijn luie verzamelingen van meerdere waarden in de loop van de tijd.

BehaviorSubject: een onderwerp dat een initiële waarde vereist en de huidige waarde aan nieuwe abonnees doorgeeft.

// RxJS v6+
import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject(123);
//two new subscribers will get initial value => output: 123, 123
subject.subscribe(console.log);
subject.subscribe(console.log);
//two subscribers will get new value => output: 456, 456
subject.next(456);
//new subscriber will get latest value (456) => output: 456
subject.subscribe(console.log);
//all three subscribers will get new value => output: 789, 789, 789
subject.next(789);
// output: 123, 123, 456, 456, 456, 789, 789, 789

Antwoord 11

Het onderwerp in rxjs is in wezen een waarnemer en een waarneembare puree samen. Waarnemer is iets dat we in waarden gooien, waarneembaar is iets waar we naar kunnen kijken voor waarden.

  • Onderwerp is standaard Hot. Waarneembare standaard zijn koud. Dat betekent dat ze geen waarden zullen uitzenden totdat iemand zich erop abonneert. Op het moment dat we een onderwerp maken, kunnen we er een waarde uitsturen en die waarde wordt uitgezonden, zelfs als er nog niemand op is geabonneerd.
  • Onderwerp is standaard multicast. Waarneembaar zijn standaard unicast en dat betekent dat we voor elke verschillende waarnemer die we hebben, ons moeten abonneren op een waarneembaar, als dat waarneembare een waarde uitstraalt, gaat die waarde eenmaal door alle verschillende operators in onze pijp voor elke abonnee . Multicast betekent dat alle andere operators één keer worden uitgevoerd voor elke waarde, ongeacht het aantal waarnemers dat we hebben.
  • GOTCHA= het ONDERWERP is multicast, maar als je er een pipe-statement aan koppelt, levert dat een nieuw waarneembaar bestand op dat koud en unicast is.

Gedrag subject is hetzelfde als subject, maar heeft ook een initiële “seed” waarde. Nieuwe abonnees krijgen direct de meest recente waarde. Als iemand zich ooit abonneert op het onderwerp Gedrag, zal het onmiddellijk de meest recente waarde ontvangen. Dus het gedragsonderwerp zal altijd enige waarde hebben om aan een abonnee te geven.

Het nuttigste aan een gedragsonderwerp is wanneer we netwerkverzoeken beginnen te maken. Stel je voor dat we wat piping-dingen aan een gedragsonderwerp hebben geketend en binnen een pijpfunctie of een pijpoperator, we uiteindelijk een netwerkverzoek doen en wat gegevens ophalen. Misschien wil je op den duur iets anders abonneren op dat waarneembare en meteen krijgen de gegevens die al zijn opgehaald. Met behulp van een gedragsonderwerp kunnen we dat soort gedrag gemakkelijk implementeren.


Antwoord 12

BehaviorSubject

Het BehaviourSubject bouwt voort op dezelfde functionaliteit als ons ReplaySubject, subject like, hot en herhaalt de vorige waarde.

Het BehaviourSubject voegt nog een stukje functionaliteit toe doordat je het BehaviourSubject een beginwaarde kunt geven. Laten we die code eens bekijken

import { ReplaySubject } from 'rxjs';
const behaviorSubject = new BehaviorSubject(
  'hello initial value from BehaviorSubject'
);
behaviorSubject.subscribe(v => console.log(v));
behaviorSubject.next('hello again from BehaviorSubject');

Waarneembare

Om te beginnen gaan we kijken naar de minimale API om een ​​normale Observable te maken. Er zijn een aantal manieren om een ​​Observable te maken. De manier waarop we onze Observable zullen maken, is door de klasse te instantiëren. Andere operators kunnen dit vereenvoudigen, maar we willen de instantiatiestap vergelijken met onze verschillende waarneembare typen

import { Observable } from 'rxjs';
const observable = new Observable(observer => {
  setTimeout(() => observer.next('hello from Observable!'), 1000);
});
observable.subscribe(v => console.log(v));

Other episodes