I recently came across MkDocs-Material by Martin Donath, a fantastic open-source project with over 22k GitHub stars.
It’s an incredible contribution to the community, making documentation hosting effortless.
While exploring it, I got curious about how such a large project achieves reactiveness.
The stack is mostly HTML, SCSS, Preact, RxJS, and a few workers, and I saw this as the perfect opportunity to dive into RxJS—especially how it utilizes Observables and other advanced patterns.
I wrote an article on operators yesterday, check it out:
![lovestaco](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1002302%2F5233b7df-6ee3-46b2-b8d7-1fafe103e8a3.jpg)
Operators & Chill: Getting Started with RxJS - II
Athreya aka Maneshwar ・ Feb 12
![lovestaco](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1002302%2F5233b7df-6ee3-46b2-b8d7-1fafe103e8a3.jpg)
Observables & Chill: Getting Started with RxJS - I
Athreya aka Maneshwar ・ Feb 11
One powerful yet often misunderstood feature in RxJS is Subjects and Multicasting.
If you've worked with Observables, you know they emit values to subscribers, but Subjects take this up a notch by allowing direct emission of values and sharing data across multiple subscribers.
Let's dive in!
What Is a Subject?
A Subject in RxJS is essentially an Observable with extra features. It allows you to:
-
Emit new data to subscribers at any time using
.next()
. - Act as both an Observable and an Observer (you can subscribe to it and push values into it).
- Broadcast values to multiple subscribers, unlike a regular Observable that sends data individually per subscription.
Example: Creating and Using a Subject
import { Subject } from 'rxjs';
const subject = new Subject();
// Subscribers
subject.subscribe(value => console.log(`Subscriber 1: ${value}`));
subject.subscribe(value => console.log(`Subscriber 2: ${value}`));
// Emit values
subject.next('Hello, RxJS!');
subject.next('Subjects are powerful!');
How It Works:
- Two subscribers listen to the same Subject.
- When we call
.next()
, both subscribers receive the value simultaneously. - Unlike standard Observables, we don’t need a separate producer—we control emissions directly.
This makes Subjects great for real-time data streaming, such as WebSocket updates, user interactions, or shared state management.
Multicasting: Avoiding Unnecessary Side Effects
By default, Observables create a new execution for each subscription, meaning if you have multiple subscribers, the data source runs multiple times.
Example: Problem with Multiple Subscribers
import { Observable } from 'rxjs';
const observable = new Observable(subscriber => {
console.log('New subscriber - fetching data...');
subscriber.next(Math.random()); // Simulating an API call
});
observable.subscribe(value => console.log(`Subscriber 1: ${value}`));
observable.subscribe(value => console.log(`Subscriber 2: ${value}`));
Output:
New subscriber - fetching data...
Subscriber 1: 0.12345
New subscriber - fetching data...
Subscriber 2: 0.67890
Each subscription triggers a new execution, leading to redundant API calls, computations, or event listeners. This is where multicasting comes in.
Using .multicast()
to Share Data
What is .multicast()
?
.multicast()
is an operator that allows multiple subscribers to share a single execution of an Observable, avoiding unnecessary repetitions.
Example: Multicasting Click Events
import { fromEvent, Subject } from 'rxjs';
import { tap, multicast } from 'rxjs/operators';
const clicks = fromEvent(document, 'click').pipe(
tap(() => console.log('Click event triggered')), // Side effect
multicast(() => new Subject())
);
const subscription = clicks.connect();
clicks.subscribe(() => console.log('Subscriber 1 received click event'));
clicks.subscribe(() => console.log('Subscriber 2 received click event'));
Why This Works Better:
- Instead of logging
"Click event triggered"
twice per click, it runs only once. - Both subscribers receive the same event data.
-
.connect()
ensures the shared execution starts immediately.
Subjects vs. Multicasting: When to Use What?
Feature | Subjects | Multicasting |
---|---|---|
Control over emissions | ✅ Yes | ❌ No (depends on source Observable) |
Broadcast values to multiple subscribers | ✅ Yes | ✅ Yes |
Avoid redundant execution | ❌ No | ✅ Yes |
Ideal for state sharing | ✅ Yes | ❌ No |
- Use Subjects when you need a manually controlled data source (e.g., WebSocket messages, user actions).
- Use Multicasting when you have a single source (like an API or event listener) but multiple subscribers.
Wrapping Up
Subjects and multicasting are powerful tools in RxJS that allow efficient data sharing.
Whether you need real-time data propagation with Subjects or execution optimization with Multicasting, these concepts make reactive programming more efficient.
I’ll be sharing more learnings, so stick around/follow for more deep dives into RxJS and beyond! 🚀
While exploring mkdocs-material implementation, I've been learning how to adapt these techniques for LiveAPI, a product I've been passionately working on for quite a while.
With LiveAPI, you can quickly generate interactive API documentation that allows users to execute APIs directly from the browser.
If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.
Top comments (0)