Chapter 14: Observables in JavaScript (RxJS)
Observables are a powerful feature from the RxJS
library, used to handle asynchronous data streams in JavaScript. They offer a more flexible alternative to Promises, especially for tasks involving real-time or multi-value streams such as WebSockets, form events, or live data.
π Recap: Promises for Async Operations
const promise = new Promise(resolve => {
setTimeout(() => {
resolve('This is example of Promise');
}, 2000);
});
promise.then(value => console.log(value));
Promises handle a single async response. But what if we want to handle **multiple values over time**? Thatβs where Observables shine.
π¦ Introduction to RxJS Observables
Observables are not built into JavaScript. They are provided by the external library RxJS (Reactive Extensions for JavaScript). RxJS is commonly used in Angular and React ecosystems.
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
setTimeout(() => {
observer.next('This is an Observable example!');
}, 2000);
});
observable.subscribe(value => console.log(value));
Key Concepts:
Observable
: a stream of valuesObserver
: receives the emitted valuessubscribe()
: listens for the emitted valuesobserver.next()
: emits a value
π Operators β Transform and Filter Streams
Operators help manipulate stream data just like array methods. Commonly used RxJS operators include map()
, filter()
, reduce()
, and more. They are applied using the pipe()
method.
import { interval } from 'rxjs';
import { map, filter } from 'rxjs/operators';
interval(1000)
.pipe(
map(value => value * value),
filter(value => value % 2 === 0)
)
.subscribe(value => console.log(value));
This example squares the emitted values and filters out the odd ones.
π Observable vs Promise
Feature | Promise | Observable |
---|---|---|
Value type | Single value | Multiple values over time |
Cancelable | No | Yes (via unsubscribe() ) |
Lazy execution | Immediately executes | Executes when subscribe() is called |
Operators | Not available | Many operators like map , filter , take |
π§ͺ Example: Button Auth with Observable
<button class="btn btn-default">Validate</button>
<div id="status"></div>
const button = document.querySelector("button");
const div = document.getElementById("status");
const checkAuth = () => Rx.Observable.create(observer => {
div.textContent = 'Validating...';
setTimeout(() => observer.next(true), 2000);
});
const fetchUser = () => Rx.Observable.create(observer => {
div.textContent = 'Fetching Information...';
setTimeout(() => observer.next({ name: 'Authenticated!!' }), 2000);
});
Rx.Observable.fromEvent(button, 'click')
.switchMap(() => checkAuth())
.switchMap(isAuth => isAuth ? fetchUser() : Rx.Observable.empty())
.subscribe(user => {
div.textContent = user.name;
});
π Example: Streaming and Reducing Values
const numbers = [1, 2, 3, 4, 5, 6];
const stream$ = Rx.Observable.interval(500)
.take(6)
.map(i => numbers[i]);
const result$ = stream$
.filter(n => n > 3)
.reduce((acc, val) => acc + val, 0);
stream$.subscribe(n => console.log('Streaming:', n));
result$.subscribe(sum => console.log('Sum > 3:', sum));
π Assignments: Practice with RxJS Observables
- Create a basic Observable that emits three values and logs them using
subscribe()
. - Use
setTimeout
inside an Observable to emit after 2 seconds. - Chain
map
andfilter
operators to square values and exclude odd results. - Try
fromEvent()
with a button and display the number of clicks in a div. - Create a custom stream from an array and reduce it using
reduce()
.
π Summary
- Observables allow multiple async values over time.
- Provided by the RxJS library, not native to JavaScript.
- Great for real-time data streams, events, and sockets.
- Operators like
map()
,filter()
, andreduce()
give powerful stream control. - Can be cancelled anytime using
unsubscribe()
.