Ik ben op zoek naar Angular RxJs-patronen en ik begrijp het verschil niet tussen een BehaviorSubject
en een Observable
.
Voor zover ik weet, is een BehaviorSubject
een 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 Observable
versus een BehaviorSubject
gebruiken? Zijn er voordelen aan het gebruik van een BehaviorSubject
boven een Observable
of omgekeerd?
Antwoord 1, autoriteit 100%
BehaviorSubjectis een type onderwerp, een onderwerp is een speciaal type waarneembaar, zodat je je kunt abonneren op berichten 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()
- Bij inschrijving wordt de laatste waarde van het onderwerp geretourneerd. Een normale waarneembare trigger wordt alleen geactiveerd wanneer deze een
onnext
- u kunt op elk moment de laatste waarde van het onderwerp in een niet-waarneembare code ophalen met behulp van de
getValue()
-methode.
heeft ontvangen
. ontvangt
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 krijgen met behulp van de asObservable()
-methode op BehaviorSubject
.
Observableis een generiek, en BehaviorSubject
is technisch gezien een subtype van Observable omdat BehaviourSubject 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 Subject
als BehaviorSubject
met 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 BehaviorSubject
gebruiken voor een gegevensservice, aangezien een hoekservice vaak wordt geïnitialiseerd voordat component en gedragssubject ervoor zorgen dat de component die 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>
Antwoord 3, autoriteit 7%
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 werkelijke uitvoer te zien)
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-ontwerppatroon 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 Subject
delen.
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.html
door:
<div *ngIf="message">
{{message}}
</div>
<app-home>
</app-home>
Voer de opdracht ng g c components/home
uit om de home-component te genereren. Vervang de inhoud van home.component.html
door:
<input type="text" placeholder="Enter message" #message>
<button type="button" (click)="setMessage(message)" >Send message</button>
#message
is 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 Subject
in 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.ts
en geef een instantie ervan door aan de constructor. Doe dit ook voor app.component.ts
. Gebruik deze service-instantie om de waarde van #message
door 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.ts
kunt 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 #message
van home.component.html
wordt 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 als 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");
gedrag.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
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 10
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 observeerbare typen
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
setTimeout(() => observer.next('hello from Observable!'), 1000);
});
observable.subscribe(v => console.log(v));
Antwoord 11
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 normaal waarneembaar signaal wordt alleen geactiveerd wanneer het 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.