Learn RxJS
  • Introduction
  • Learn RxJS
    • Operators
      • Combination
        • combineAll
        • combineLatest
        • concat
        • concatAll
        • endWith
        • forkJoin
        • merge
        • mergeAll
        • pairwise
        • race
        • startWith
        • withLatestFrom
        • zip
      • Conditional
        • defaultIfEmpty
        • every
        • iif
        • sequenceEqual
      • Creation
        • ajax
        • create
        • defer
        • empty
        • from
        • fromEvent
        • generate
        • interval
        • of
        • range
        • throw
        • timer
      • Error Handling
        • catch / catchError
        • retry
        • retryWhen
      • Multicasting
        • publish
        • multicast
        • share
        • shareReplay
      • Filtering
        • audit
        • auditTime
        • debounce
        • debounceTime
        • distinct
        • distinctUntilChanged
        • distinctUntilKeyChanged
        • filter
        • find
        • first
        • ignoreElements
        • last
        • sample
        • single
        • skip
        • skipUntil
        • skipWhile
        • take
        • takeLast
        • takeUntil
        • takeWhile
        • throttle
        • throttleTime
      • Transformation
        • buffer
        • bufferCount
        • bufferTime
        • bufferToggle
        • bufferWhen
        • concatMap
        • concatMapTo
        • exhaustMap
        • expand
        • groupBy
        • map
        • mapTo
        • mergeMap / flatMap
        • mergeScan
        • partition
        • pluck
        • reduce
        • scan
        • switchMap
        • switchMapTo
        • toArray
        • window
        • windowCount
        • windowTime
        • windowToggle
        • windowWhen
      • Utility
        • tap / do
        • delay
        • delayWhen
        • dematerialize
        • finalize / finally
        • let
        • repeat
        • timeInterval
        • timeout
        • timeoutWith
        • toPromise
      • Full Listing
    • Subjects
      • AsyncSubject
      • BehaviorSubject
      • ReplaySubject
      • Subject
    • Recipes
      • Alphabet Invasion Game
      • Battleship Game
      • Breakout Game
      • Car Racing Game
      • Catch The Dot Game
      • Click Ninja Game
      • Flappy Bird Game
      • Game Loop
      • Horizontal Scroll Indicator
      • Http Polling
      • Lockscreen
      • Matrix Digital Rain
      • Memory Game
      • Mine Sweeper Game
      • Platform Jumper Game
      • Progress Bar
      • Save Indicator
      • Smart Counter
      • Space Invaders Game
      • Stop Watch
      • Swipe To Refresh
      • Tank Battle Game
      • Tetris Game
      • Type Ahead
      • Uncover Image Game
    • Concepts
      • RxJS Primer
      • Get started transforming streams with map, pluck, and mapTo
      • Time based operators comparison
      • RxJS v5 -> v6 Upgrade
Powered by GitBook
On this page
  • Requires an initial value and emits the current value to new subscribers
  • Why use BehaviorSubject?
  • Examples
  • Related Recipes
  • Additional Resources
  1. Learn RxJS
  2. Subjects

BehaviorSubject

PreviousAsyncSubjectNextReplaySubject

Last updated 1 year ago

Requires an initial value and emits the current value to new subscribers


💡 If you want the last emitted value(s) on subscription, but do not need to supply a seed value, check out instead!


Why use BehaviorSubject?

This specialized subject is ideal when you want to maintain and provide a "current value" to subscribers. Think of it as a scoreboard in a basketball game. Even if you join watching in the middle of the game, you'll still see the current score. Similarly, when a new observer subscribes to a BehaviorSubject, it immediately receives the current value (or the last value that was emitted).

It's important to remember that a BehaviorSubject requires an initial value upon instantiation. This is where it differs from a regular which doesn't have an initial value. Picture a newly installed scoreboard – with BehaviorSubject, you set a starting score, say 0-0. With a regular , the board remains blank until a point is scored. Subscribers (early or late) of a normal will not receive emissions until the Subject emits a value.

Contrasting with , while both provide historical values, can relay multiple previous values, not just the last one. If the basketball scoreboard could show the last five scores in the match sequence, that'd be akin to . also does not receive an initial seed value.

In conclusion, if you need to ensure subscribers always get the latest value upon subscription, or you have an initial seed value, BehaviorSubject is your pick. If you need more historical emissions, consider . And if you don't need any history at all, a simple might be what you're looking for.

Examples

Example 1: Simple BehaviorSubject

( )

// 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

Example 2: BehaviorSubject with new subscribers created on mouse clicks

// RxJS v6+
import { BehaviorSubject, fromEvent, interval, merge } from 'rxjs';
import { map, tap, mergeMap } from 'rxjs/operators';

const setElementText = (elemId, text) =>
  (document.getElementById(elemId).innerText = text.toString());
const addHtmlElement = coords =>
  (document.body.innerHTML += `
  <div 
    id=${coords.id}
    style="
      position: absolute;
      height: 30px;
      width: 30px;
      text-align: center;
      top: ${coords.y}px;
      left: ${coords.x}px;
      background: silver;
      border-radius: 80%;"
    >
  </div>`);

const subject = new BehaviorSubject(0);

const click$ = fromEvent(document, 'click').pipe(
  map((e: MouseEvent) => ({
    x: e.clientX,
    y: e.clientY,
    id: Math.random()
  })),
  tap(addHtmlElement),
  mergeMap(coords => subject.pipe(tap(v => setElementText(coords.id, v))))
);

const interval$ = interval(1000).pipe(
  tap(v => subject.next(v)),
  tap(v => setElementText('intervalValue', v))
);

merge(click$, interval$).subscribe();

Related Recipes

Additional Resources


( )

📰 - Official docs

- In Depth Dev Reference

📁 Source Code:

Stackblitz
Alphabet Invasion Game
Battleship Game
Car Racing Game
BehaviorSubject
BehaviorSubject
https://github.com/ReactiveX/rxjs/blob/master/src/internal/BehaviorSubject.ts
ReplaySubject
Subject
Subject
Subject
ReplaySubject
ReplaySubject
ReplaySubject
ReplaySubject
ReplaySubject
Subject
Stackblitz