DEV Community

Cover image for Observables & Chill: Getting Started with RxJS - I
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

Observables & Chill: Getting Started with RxJS - I

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.

So, let’s break down RxJS from the ground up and see what makes it tick!


What is RxJS?

RxJS (Reactive Extensions for JavaScript) is a library for composing asynchronous and event-based programs using Observables.

Think of Observables as data streams you can listen to, transform, combine, and control with precision.

In simpler terms: RxJS helps you manage async data like a pro.


Why Should You Care?

Here’s why RxJS is worth your attention:

  • Declarative Approach: Focus on what to do with data, not how to manage it.
  • Powerful Operators: Transform, filter, and combine streams with ease.
  • Versatile: Perfect for handling user interactions, HTTP requests, WebSockets, and more.

Image description

Getting Started

First, install RxJS with npm:

npm install rxjs
Enter fullscreen mode Exit fullscreen mode

Creating Observables

1. From Scratch

You can create an observable using new Observable().

Inside it, you define what to send to subscribers using observer.next(). This can be literally anything—a string, an object, even your to-do list (though maybe don’t do that).

To get things rolling, just call subscribe(), which makes the observable start firing off those values.

Here’s a quick example:

import { Observable } from 'rxjs';

const customObservable = new Observable(observer => {
  observer.next('Hi');
  observer.next('Mom');
  observer.complete();
});

customObservable.subscribe({
  next: value => console.log(value),
  complete: () => console.log(`I'm Done!`)
});

// Output:

// Hi
// Mom
// I'm Done!
Enter fullscreen mode Exit fullscreen mode

Boom! Values are sent, received, and when there’s nothing left to say, complete() wraps it up like a polite email sign-off.

2. From DOM Events

Want to react to user clicks?

Just use fromEvent().

Pass in the DOM element and the event you care about—like click.

import { fromEvent } from 'rxjs';

const button = document.getElementById('myButton');

const clicks$ = fromEvent(button, 'click');

clicks$.subscribe(() => console.log('Button clicked!'));
Enter fullscreen mode Exit fullscreen mode

Now, every time someone clicks the button, it logs “Button clicked!” Simple, right?

You could even hook this up to rage-click counters.

3. From Promises

Got a promise?

You can turn it into an observable with from().

This is super handy when dealing with promise-based libraries.

import { from } from 'rxjs';

const promise = new Promise(resolve => setTimeout(() => resolve('Resolved!'), 1000));

const observableFromPromise = from(promise);

observableFromPromise.subscribe(value => console.log(value));

// Converting back to a promise
observableFromPromise.toPromise().then(console.log);

// Output
// Resolved.
Enter fullscreen mode Exit fullscreen mode

This simulates an API call (aka: fake waiting).

After one second, it logs “Resolved!” Oh, and if you ever miss promises that much, you can flip it back with toPromise().

4. Static Values

Need to turn random data into an observable?

Use of(). It doesn’t care what you throw at it—numbers, strings, booleans, objects, your grocery list…

import { of } from 'rxjs';

const staticValues$ = of(1, 'RxJS', true, { key: 'value' });

staticValues$.subscribe(value => console.log(value));

// Output:
// 1
// RxJS
// true
// { key: 'value' }
Enter fullscreen mode Exit fullscreen mode

Basically, anything can be part of a stream.

Yes, anything. Even your existential crisis.

Image description

5. Timers and Intervals

If you need to fire events after a delay or at regular intervals, RxJS has your back:

  • Timers trigger once after a set delay.
  • Intervals keep firing like an overenthusiastic alarm clock.
import { timer, interval } from 'rxjs';

// Emits once after 2 seconds
timer(2000).subscribe(() => console.log('Timer fired!'));

// Emits every second
interval(1000).subscribe(count => console.log(`Count: ${count}`));
Enter fullscreen mode Exit fullscreen mode

timer() waits politely before saying anything, while interval() just can’t stop talking—perfect for regular updates (or if you’re trying to annoy your console).

Image description

Wrapping Up

RxJS might feel overwhelming at first, but once you get the hang of it, you’ll wonder how you ever managed async code without it.

Start small, experiment, and soon you’ll be chaining Observables like a boss.

This is just the beginning(observable)—there’s so much more to explore in RxJS, from advanced operators to real-world patterns.

I’ll be sharing more learnings, so stick around/follow for more deep dives into RxJS and beyond! 🚀

Got questions about Observables or cool RxJS tricks? Drop them in the comments below!

Checkout others:

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.

Image description

If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.

Top comments (0)