Here are my detailed notes from the fantastic course created by Jurek Wozniak, called RxJS 7 and Observables: Introduction.
In order to understand the concept please consider buying the course yourself, these notes are simply subsidiaries
Subjects allow us to multicast notifications to multiple observers, because of it is using a shared resource, it is a hot observable.
Subjects work like event emitters, they emit events and all the observers that are subscribed to it, react to those multicasted events.
Subjects has 2 natures: observable and observer. They can be subscribe-able like normal observables. But at the same time can be used .next() .error() and .complete() like an observer.
Subjects in Action
import { fromEvent, Subject } from 'rxjs';
import { map } from 'rxjs/operators';
const emitButton = document.querySelector('button#emit');
const inputElement: HTMLInputElement = document.querySelector('#value-input');
const subscribeButton = document.querySelector('button#subscribe');
const value$ = new Subject<string>();
fromEvent(emitButton, 'click').subscribe(() => value$.next(inputElement.value));
fromEvent(subscribeButton, 'click').subscribe(() => {
console.log('New Subscription');
value$.subscribe((value) => console.log(value));
});
After we subscribe we could emit to multiple observers.
We could also emit a value directly by passing the subject, there is no need to specifically call next in subject.
fromEvent(emitButton, 'click')
.pipe(map(() => inputElement.value))
.subscribe(value$);
BehaviourSubject – Concept
Let’s say we have a subject and 2 observers,
Subject is emitting match scores and 2 observers since they followed the match since the beginning know the score (2:1).
Let’s say we have one more observer that has joined, the new observer will not have an opportunity to know the score until a new notification is emitted.
In order to solve this there is another subject type called BehaviourSubject, this subject emits the latest notification to the newly joined observers, when they join.
import { BehaviorSubject, fromEvent, Subject } from "rxjs";
import { withLatestFrom } from "rxjs/operators";
const loggedInSpan: HTMLElement = document.querySelector('span#logged-in');
const loginButton: HTMLElement = document.querySelector('button#login');
const logoutButton: HTMLElement = document.querySelector('button#logout');
const printStateButton: HTMLElement = document.querySelector('button#print-state');
const isLoggedIn$ = new BehaviorSubject<boolean>(false);
fromEvent(loginButton, 'click').subscribe(() => isLoggedIn$.next(true));
fromEvent(logoutButton, 'click').subscribe(() => isLoggedIn$.next(false));
// Navigation bar
isLoggedIn$.subscribe(
isLoggedIn => loggedInSpan.innerText = isLoggedIn.toString()
);
// Buttons
isLoggedIn$.subscribe(isLoggedIn => {
logoutButton.style.display = isLoggedIn ? 'block' : 'none';
loginButton.style.display = !isLoggedIn ? 'block' : 'none';
});
fromEvent(printStateButton, 'click').pipe(
withLatestFrom(isLoggedIn$)
).subscribe(
([event, isLoggedIn]) => console.log('User is logged in:', isLoggedIn)
);
We see that for the BehaviourSubjects we need to provide an initial value
Let’s keep in touch
Hey, thanks a lot if you read it so far.
I want you to keep in touch for more sweet content.
Please subscibe in Dev.to and other channels (🦸♂️ especially twitter)
Twitter 🐦 https://twitter.com/barisbll_dev
Linkedin 📎 https://www.linkedin.com/in/barisbll-dev/
Github 👨🏻💻 https://github.com/barisbll
Medium 📰 https://medium.com/@barisbll