angular - Vad är skillnaden mellan Subject och BehaviorSubject?


Jag är inte säker på skillnaden mellan en Subject och en BehaviorSubject. Är det bara det att en BehaviorSubject har getValue()-funktionen?

Svar #1

En BehaviorSubject håller ett värde. När den prenumereras på skickar den värdet omedelbart. En Subject håller inget värde.

Exempel på Subject (med RxJS 5 API):

const subject = new Rx.Subject();
subject.next(1);
subject.subscribe(x => console.log(x));

Konsolutmatningen kommer att vara tom

Exempel på BehaviorSubject:

const subject = new Rx.BehaviorSubject(0);
subject.next(1);
subject.subscribe(x => console.log(x));

Konsolutmatning: 1

Dessutom:

  • BehaviorSubject bör skapas med ett initialt värde: new Rx.BehaviorSubject(1)
  • Överväg ReplaySubject om du vill att subjektet ska få tidigare publicerade värden.

Svar #2

BehaviourSubject

BehaviourSubject kommer att returnera det initiala värdet eller det aktuella värdet vid prenumeration

var bSubject= new Rx.BehaviorSubject(0);  // 0 is the initial value

bSubject.subscribe({
  next: (v) => console.log('observerA: ' + v)  // output initial value, then new values on `next` triggers
});

bSubject.next(1);  // output new value 1 for 'observer A'
bSubject.next(2);  // output new value 2 for 'observer A', current value 2 for 'Observer B' on subscription

bSubject.subscribe({
  next: (v) => console.log('observerB: ' + v)  // output current value 2, then new values on `next` triggers
});

bSubject.next(3);

Med utgång:

observerA: 0
observerA: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3

Ämne

Subject returnerar inte det aktuella värdet vid prenumeration. Det utlöses endast vid .next(value)-anrop och returnerar/outputterar value

var subject = new Rx.Subject();

subject.next(1); //Subjects will not output this value

subject.subscribe({
  next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
  next: (v) => console.log('observerB: ' + v)
});

subject.next(2);
subject.next(3);

Med följande utskrift på konsolen:

observerA: 2
observerB: 2
observerA: 3
observerB: 3

Svar #3

Jag har precis skapade ett projekt som förklarar vad som är skillnaden mellan alla ämnen:
https://github.com/piecioshka/rxjs-subject-vs-behavior-vs-replay-vs-async

Svar #4

En BehaviorSubject håller ett värde (så vi behöver faktiskt initiera ett standardvärde). När det abonneras på skickar det ut det värdet omedelbart. En Subject å andra sidan, håller inget värde.

Det det egentligen betyder är att i Subject kommer prenumeranterna endast att ta emot det kommande värdet medan i BehaviorSubject kommer prenumeranterna att ta emot det tidigare värdet och även det kommande värdet.

Så, låt oss ta ett exempel för att se hur detta kommer att bete sig:

let mySubject = new Subject<number>();

mySubject.subscribe(x => console.log("The first Subscription : " + x));

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

mySubject.subscribe(x => console.log("The second Subscription : " + x));

mySubject.next(3);

// The first Subscription : 1
// The first Subscription : 2
// The first Subscription : 3
// The second Subscription : 3

Som vi såg ovan, de första 2 värdena skickades ut från subjektet innan den andra prenumerationen registrerades, så den fick dem inte, den fick bara de nya värdena efter att ha prenumererat. Den första prenumerationen fick dem alla, eftersom den prenumererade innan de första värdena skickades ut.

Nu, låt oss ändra subject till BehaviorSubject och se skillnaden:

let mySubject = new BehaviorSubject<number>(0);

mySubject.subscribe((x) => console.log('The first Subscription : ' + x));

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

mySubject.subscribe((x) => console.log('The second Subscription : ' + x));

mySubject.next(3);

// The first Subscription : 0 (since it's the initial value)
// The first Subscription : 1
// The first Subscription : 2
// The second Subscription : 2 (since it's the initial value for the seconde subscriber)
// The first Subscription : 3
// The second Subscription : 3

Observera nu hur den första prenumeranten outputar 0 eftersom BehaviorSubject initialiserades med 0. När den andra prenumeranten prenumererar, skickar den omedelbart värdet '2' eftersom det var det sista värdet som hanterades, så det fungerar som startvärde för den.

Mer om skillnaden mellan BehaviorSubject och Subject kan hittas här

Svar #5

BehaviorSubject behåller i minnet det senaste värdet som sändes av den observabla. Ett vanligt Subject gör det inte.

BehaviorSubject är som ReplaySubject med en buffertstorlek på 1.

UPPDATERING: Det finns kantfall som skiljer de två åt. https://medium.com/javascript-everyday/behaviorsubject-vs-replaysubject-1-beware-of-edge-cases-b361153d9ccf

TLDR: Om du vill ange ett initialt värde vid prenumerationstid, även om inget har skickats till ett Subject hittills, använd BehaviorSubject. Om du vill att det senaste värdet ska upprepas för en observatör, även om ett Subject redan är stängt, använd ReplaySubject(1).

Svar #6

Det kan hjälpa dig att förstå.

import * as Rx from 'rxjs';

const subject1 = new Rx.Subject();
subject1.next(1);
subject1.subscribe(x => console.log(x)); // will print nothing -> because we subscribed after the emission and it does not hold the value.

const subject2 = new Rx.Subject();
subject2.subscribe(x => console.log(x)); // print 1 -> because the emission happend after the subscription.
subject2.next(1);

const behavSubject1 = new Rx.BehaviorSubject(1);
behavSubject1.next(2);
behavSubject1.subscribe(x => console.log(x)); // print 2 -> because it holds the value.

const behavSubject2 = new Rx.BehaviorSubject(1);
behavSubject2.subscribe(x => console.log('val:', x)); // print 1 -> default value
behavSubject2.next(2) // just because of next emission will print 2 

Relaterade artiklar