I'm not clear on the difference between a Subject
and a BehaviorSubject
. Is it just that a BehaviorSubject
has the getValue()
function?

- 14,906
- 5
- 47
- 53

- 9,551
- 5
- 22
- 42
-
nice answer: https://stackoverflow.com/a/55991072/7186739 – Billu Dec 29 '21 at 07:23
-
@dev I agree... – William May 19 '22 at 07:02
10 Answers
A BehaviorSubject holds one value. When it is subscribed it emits the value immediately. A Subject doesn't hold a value.
Subject example (with RxJS 5 API):
const subject = new Rx.Subject();
subject.next(1);
subject.subscribe(x => console.log(x));
Console output will be empty
BehaviorSubject example:
const subject = new Rx.BehaviorSubject(0);
subject.next(1);
subject.subscribe(x => console.log(x));
Console output: 1
In addition:
BehaviorSubject
should be created with an initial value: newRx.BehaviorSubject(1)
- Consider
ReplaySubject
if you want the subject to get previously published values.
-
39So do you mean you have to subscribe to subject before subject.next() to for this to work? – Eric Huang Jun 28 '18 at 03:02
-
11
-
15Note that you have to pass in the first value to BehaviorSubject's constructor ;) – mrmashal Sep 23 '18 at 08:02
-
if we create subject with boolean even subject emits rite?? const subject = new Subject
(); subject.next(true); – user2900572 Feb 26 '20 at 07:20 -
6
-
When you say "A Subject doesn't hold a value" it's kind of confusing. If you show one more example for "Subject" where you subscribe first and _then_ call `.next(1)`, it will make your answer a lot more clear. – Sergey Jun 05 '20 at 17:14
-
Often, we do not have the initial value, since we would like to [convert an observable to behavior subject](https://stackoverflow.com/a/58199823/5770014): don't worry about the initial value, just use some 'empty' value. – minus one Dec 13 '21 at 09:14
-
I think the answer below has a better example. https://stackoverflow.com/a/59784108/12097072 – stoneshishang Sep 21 '22 at 16:20
BehaviourSubject
BehaviourSubject will return the initial value or the current value on Subscription
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);
With output:
observerA: 0
observerA: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3
Subject
Subject does not return the current value on Subscription. It triggers only on .next(value)
call and return/output the 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);
With the following output on the console:
observerA: 2
observerB: 2
observerA: 3
observerB: 3

- 1,608
- 1
- 27
- 40

- 20,751
- 8
- 75
- 78
-
36Its also more correct : "BehaviourSubject will return the initial value or the current value on Subscription" is a better explanation than "A BehaviorSubject holds one value." – Davy Jun 22 '18 at 13:28
-
1I put the code above on Stackblitz: https://stackblitz.com/edit/rxjs-subjectvsbehaviorsubject – Fredrik_Borgstrom Oct 26 '18 at 22:22
-
-
-
I just created a project which explain what is the difference between all subjects:
https://github.com/piecioshka/rxjs-subject-vs-behavior-vs-replay-vs-async

- 4,752
- 2
- 20
- 29
-
4
-
3Wow, I wish the official documentation would be that simple and helpful, thanks! – Tom Mar 25 '22 at 10:46
-
1you made it very simple @piecioshka. thanks, lots you saved time & effort both to understand this basic concept. – Santosh Kori Apr 06 '23 at 05:19
A BehaviorSubject
holds one value (so we actually need to initialize a default value). When it is subscribed it emits that value immediately. A Subject
on the other hand, does not hold a value.
What it actually means is that in Subject
, the subscribers will only receive the upcoming value where as in BehaviorSubject
the subscribers will receive the previous value and also upcoming value.
So, let's take an example to see how this will behave:
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
Like we saw above, the first 2 values were output from the subject before the second subscription registered, so it didn't get them, it only got the new values after subscribed. The first subscription got them all, since it subscribed before the first values were output.
Now, let's change the subject
to BehaviorSubject
and see the difference:
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
Now, notice how the first subscriber outputs 0
since the BehaviorSubject
was initialized with 0
. When the second subscriber subscribes, it immediately emits the '2' value since it was the last value to be handled so it acts as the initial value for it.
More about the difference between BehaviorSubject
and Subject
can be found here

- 14,906
- 5
- 47
- 53
-
2@Rad thank you for you explanation -> it really made sense to me – Ursus Schneider Mar 17 '22 at 09:39
BehaviorSubject
keeps in memory the last value that was emitted by the observable. A regular Subject
doesn't.
BehaviorSubject
is like ReplaySubject
with a buffer size of 1.
UPDATE: There are edge use cases that distinguish those two. https://medium.com/javascript-everyday/behaviorsubject-vs-replaysubject-1-beware-of-edge-cases-b361153d9ccf
TLDR: If you want to provide an initial value at subscription time, even if nothing has been pushed to a Subject so far, use the BehaviorSubject. If you want to have the last value replayed to an observer, even if a Subject is already closed, use the ReplaySubject(1).

- 608
- 9
- 13
It might help you to understand.
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

- 3,333
- 3
- 17
- 26
A BehaviorSubject emits a value after subscription, a Subject no.
// Subject
const mySubject = new Rx.Subject().subscribe((v) => console.log(v)); // will return nothing
// BehaviorSubject
const myBehaviorSubject = new Rx.BehaviorSubject(666).subscribe((v) => console.log(v)); // will return 666 when subscription occurs

- 21
- 4
BehaviorSubject keeps in memory the last value that was emitted by the observable. A regular Subject doesn't. So we can update dynamic titles based on Behaviour Subject.
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);
- With Output

- 3
- 3

- 558
- 4
- 13
All three are quite different, let me give few more samples here,
const subject = new Rx.Subject();
const behaviorSubject = new Rx.BehaviorSubject([]);
const relaySubject = new Rx.ReplaySubject();
subject.next(1)
behaviorSubject.next(1);
behaviorSubject.next(2);
behaviorSubject.next(3);
relaySubject.next(1);
relaySubject.next(2);
relaySubject.next(3);
subject.subscribe(val => console.log('From Subject', val)); // this will not emits
behaviorSubject.subscribe(val => console.log('From BehaviorSubject', val)); // this will emits only last value
relaySubject.subscribe(val => console.log('From ReplaySubject', val)); // this will emit all values
As you can see, when we subscribe to the subject after we emit(i.e next(...)),
- subject - this will not get fired at all
- behaviorSubject - this will fire once with last value
- ReplaySubject - this will fire 3 time, as many
next()
we have
So the difference is mainly where you subscribe, whether it's before next()
or after next()
.
In practical case, we fire event's only after next()
[i.e after we fill data to the subjects].

- 564
- 5
- 15
Program to test all 4 Subjects types: Subject, BehaviorSubject, ReplaySubject and AsyncSubject
// 1. Subject - only value after subscribed
var subject = new Subject();
subject.next(1);
subject.next(2);
subject.complete();
subject.subscribe(
(data) => this.log("Subject="+data),
(error) => this.log(error),
() => this.log('Complete Subject')
);
subject.next(3);
subject.next(4);
// 2. BehaviorSubject - only last value before subscribed and all after subscription
// calls on initalization, mandatory to specify a value
var subjectb = new BehaviorSubject<any>(5);
subjectb.next(1);
subjectb.next(2);
subjectb.complete();
subjectb.subscribe(
(data) => this.log("Behavior="+data),
(error) => this.log(error),
() => this.log('Complete Behavior')
);
// 3. ReplaySubject - all specified last values before subscribed and all after subscription
// Does not call on initalization, no default value
var subjectr = new ReplaySubject(5);
subjectr.next(1);
subjectr.next(2);
subjectr.complete();
subjectr.subscribe(
(data) => this.log("Replay="+data),
(error) => this.log(error),
() => this.log('Complete Replay')
);
// 4. AsyncSubject - only last values before calling complete
var subjecta = new AsyncSubject();
subjecta.next(1);
subjecta.next(2);
subjecta.complete();
subjecta.subscribe(
(data) => this.log("Async="+data),
(error) => this.log(error),
() => this.log('Complete Async')
);
https://stackblitz.com/edit/example-rxjs-subject-e8vj9y?embed=1&file=app/app.component.ts

- 271
- 4
- 10