Subject and BehaviorSubject: Two Acrobatic Brothers in the World of Reactive Programming
\n\nIf you've ever looked at a Stack Overflow discussion on "What is the difference between Subject and BehaviorSubject?", you know: this topic gathers thousands of views. And it's no wonder — it's one of those questions that every developer working with RxJS in TypeScript inevitably faces sooner or later.
\n\nImagine you are managing a live data broadcast. Subject is like an open microphone: whoever subscribes first will get everything that is said afterwards. And BehaviorSubject is a microphone that always stores the last phrase and immediately repeats it to a new listener. Can you feel the difference?
\n\nIn this article, we won't just paraphrase the documentation. We'll break down real-world cases, show TypeScript code examples, and give clear rules for choosing. Let's go!
\n\nWhat is Subject in TypeScript?
\n\nSubject is a special type of Observable that is also an Observer. It can receive data via the next() method and distribute it to all subscribers. But there is an important nuance: Subject does not store previous values.
A simple example in TypeScript:
\n\nimport { Subject } from 'rxjs';\n\nconst subject = new Subject<string>();\n\n// Subscribing after data has already been sent\nsubject.next('First message');\nsubject.next('Second message');\n\n// This subscriber will receive nothing\nsubject.subscribe({\n next: (value) => console.log('Subscriber:', value)\n});\n\n// This will be visible\nsubject.next('Third message');\n\n\nWhat will be printed to the console? Only "Subscriber: Third message". The first two messages are lost forever for this subscriber. This effect is called a "cold start" — you only receive data that was sent after subscribing.
\n\nBehaviorSubject: When You Need to Remember the Past
\n\nBehaviorSubject is the same as Subject, but with a superpower: it always stores the last value and provides it to a new subscriber immediately upon subscription. A mandatory condition is that you must specify an initial value.
\n\nimport { BehaviorSubject } from 'rxjs';\n\nconst behaviorSubject = new BehaviorSubject<string>('Initial value');\n\n// Subscribing — immediately receives the last value\nbehaviorSubject.subscribe({\n next: (value) => console.log('First subscriber:', value)\n});\n\nbehaviorSubject.next('First update');\nbehaviorSubject.next('Second update');\n\n// This subscriber will receive 'Second update' immediately\nbehaviorSubject.subscribe({\n next: (value) => console.log('Second subscriber:', value)\n});\n\n\nConsole output:
\nFirst subscriber: Initial value\nFirst subscriber: First update\nFirst subscriber: Second update\nSecond subscriber: Second update\n\n\nSee? The second subscriber immediately received the last value, even though they subscribed later. This is the key difference between BehaviorSubject and Subject.
\n\nComparison of Subject and BehaviorSubject: Differences Table
\n\nLet's summarize all the differences in a clear table that will come in handy in an interview or a real project.
\n\n- \n
- Initial value: Subject — none. BehaviorSubject — required. \n
- Storing the last value: Subject — does not store. BehaviorSubject — stores and provides it to a new subscriber. \n
- Behavior on late subscription: Subject — skips all previous events. BehaviorSubject — provides the last value. \n
- Use with Angular: Subject — for events (clicks, timers). BehaviorSubject — for state (user data, settings). \n
- getValue() method: Subject — absent. BehaviorSubject — exists, returns the current value synchronously. \n