Basic RxJS Course with Vanilla JavaScript
1. Introduction to Reactive Programming
Reactive programming is a way to work with data streams that change over time.
- A mouse click is an event.
- Input typing is an event.
- An HTTP response is an async event.
Instead of constantly asking if data is ready, your code reacts when data arrives.
2. What is RxJS
RxJS is a JavaScript library for composing asynchronous and event-based programs using Observables.
Quick installation
With npm:
npm install rxjsWith CDN:
<script src="https://unpkg.com/rxjs@7/dist/bundles/rxjs.umd.min.js"></script>Basic Vanilla JS structure
index.htmlapp.jsstyles.css(optional)
3. Observables
An Observable is a data source that can emit 0, 1, or many values over time.
const { of, from, interval } = rxjs;
of(1, 2, 3).subscribe(console.log); // 1, 2, 3
from(["A", "B"]).subscribe(console.log); // A, BfromEvent
const { fromEvent } = rxjs;
const button = document.getElementById("btn");
const click$ = fromEvent(button, "click");
const sub = click$.subscribe(() => console.log("click"));Subscription and unsubscription
const { interval } = rxjs;
const sub = interval(1000).subscribe(v => console.log("tick", v));
setTimeout(() => sub.unsubscribe(), 5000);4. Basic Operators
An operator is a function that transforms or filters Observable values.
const { of } = rxjs;
const { map, filter, take } = rxjs.operators;
of(1, 2, 3, 4, 5)
.pipe(
filter(n => n % 2 === 1),
map(n => n * 10),
take(2)
)
.subscribe(console.log); // 10, 30Key operators in this basic course
- Creation:
of,from,interval,timer - Transformation:
map,filter - Combination:
merge,concat - Filtering:
take,first,debounceTime
5. DOM Event Handling
Click counter
const { fromEvent } = rxjs;
const btn = document.getElementById("btn");
const output = document.getElementById("output");
let count = 0;
fromEvent(btn, "click").subscribe(() => {
count += 1;
output.textContent = `Clicks: ${count}`;
});Basic live search
const { fromEvent } = rxjs;
const { map, debounceTime } = rxjs.operators;
const input = document.getElementById("search");
fromEvent(input, "input")
.pipe(
map(e => e.target.value.trim()),
debounceTime(300)
)
.subscribe(term => console.log("Search:", term));6. Async Handling
Observables vs Promises
- Promise: usually one future value.
- Observable: multiple values over time and supports cancellation with
unsubscribe.
API calls with RxJS ajax
const { ajax } = rxjs.ajax;
ajax
.getJSON("https://jsonplaceholder.typicode.com/users")
.subscribe({
next: data => console.log("Users:", data),
error: err => console.error("HTTP error:", err),
complete: () => console.log("Completed")
});7. Error Handling and Completion
const { of } = rxjs;
const { catchError, retry } = rxjs.operators;
const { ajax } = rxjs.ajax;
ajax
.getJSON("https://api.example.com/data")
.pipe(
retry(2),
catchError(err => {
console.error("Request failed:", err);
return of([]);
})
)
.subscribe({
next: data => console.log(data),
complete: () => console.log("Finished")
});Key points:
catchError: recover or transform errors.retry: retry failed requests.complete: runs when stream finishes successfully.unsubscribe: manually stop an active stream.
8. Best Practices and Resources
- Always clean subscriptions for infinite streams (
interval,fromEvent). - Use
pipeto compose operators clearly. - Keep heavy logic out of
subscribe. - Use
tapfor quick debugging.
9. Final Project (Proposal)
Live search mini app:
- Text input.
- Listen with
fromEvent. - Apply
map+debounceTime. - Request data with
ajax.getJSON. - Render results.
- Handle errors with
catchError.
This gives you a full basic RxJS flow in one practical project.
10. Resources and Next Steps
Official docs:
Recommended exercises:
- Stopwatch with
interval. - Counter with
+and-buttons. - Live search using a public API.
- Request retries using
retry.
Suggested next step:
- Intermediate course:
switchMap,mergeMap, Subjects, and advanced stream composition.