RxJS Observables Explained
Introduction to RxJS Observables
Data Over Time
In JavaScript, we often deal with data that arrives when it's ready, not all at once. Think about user clicks, messages from a server, or even a simple countdown timer. These are all examples of asynchronous data streams—sequences of values that arrive over time.
RxJS gives us a powerful tool to manage these streams: the Observable. An Observable is an object that represents a stream of values that can be pushed to observers over time. It's like a newsletter you can subscribe to. Once you subscribe, you get notified whenever a new issue is published.
An Observable is a lazy producer of values, emitting them over time.
The Observer Pattern
Observables work using the Observer design pattern. In this pattern, you have two main players: the producer and the consumer.
- The Producer (Observable): This is the source of the data. It's responsible for creating and sending out values. It doesn't start sending anything until it has a listener.
- The Consumer (Observer): This is the listener. It subscribes to an Observable and reacts to the values it receives.
An Observer is just an object with three methods: next(), error(), and complete(). The Observable calls next() for each value it emits, error() if something goes wrong, and complete() when the stream is finished.
Key Characteristics
Observables have a few unique traits that make them different from other ways of handling asynchronous data, like Promises.
First, Observables are lazy. They don't start producing values until an Observer subscribes to them.
Consider a Promise. The moment you create it, the code inside its executor function runs immediately. An Observable, on the other hand, is just a blueprint for a stream. The code that produces values only executes when you call .subscribe().
// This Promise runs its code immediately
const myPromise = new Promise(resolve => {
console.log('Promise is running!');
resolve('Hello');
});
// This Observable does nothing yet
const myObservable = new Rx.Observable(observer => {
console.log('Observable is running!');
observer.next('Hello');
observer.complete();
});
// ...only when we subscribe does it run.
myObservable.subscribe(value => console.log(value));
Second, an Observable can emit multiple values over time. A Promise can only resolve or reject once. This makes Observables perfect for handling ongoing events like mouse movements, keyboard input, or data from a real-time connection. A stream can even be infinite, never calling complete().
Observable vs. Promise
Here’s a quick comparison to help solidify the differences.
| Feature | Promise | Observable |
|---|---|---|
| Values | Emits a single value | Emits multiple values over time |
| Execution | Eager (runs immediately) | Lazy (runs on subscription) |
| Cancellable | No | Yes (by unsubscribing) |
| Type | Always asynchronous | Can be synchronous or asynchronous |
Understanding these core concepts is the first step to harnessing the power of reactive programming with RxJS. Let's check your knowledge.
What is the primary role of an RxJS Observable?
In the context of RxJS, an Observer is an object with three methods. What are they?
Now that you understand what an Observable is and its basic properties, you're ready to see how to create and use them.