The Asynchronous Duel: Promises vs Observables
In modern web development, particularly within the Angular ecosystem, handling asynchronous operations—like HTTP requests, timers, or user input events—is a daily task. Two primary contenders vie for control over your async logic: the native JavaScript **Promise** and the RxJS **Observable**.
The Fundamental Difference: One vs. Many
The most distinct difference lies in how many values each can produce.
- Promise: Resolves to a single value (or rejects with an error) and then completes. It is ideal for "one-and-done" operations, like fetching a configuration file at app startup.
- Observable: Represents a stream of values over time. It can emit zero, one, or infinite values. This makes it perfect for "ongoing" events, like WebSocket messages, mouse movements, or search bar inputs.
Eager vs. Lazy Execution
This is often the source of bugs for beginners.
Promises are Eager
The moment you invoke the Promise constructor, the code inside runs. You cannot stop it from starting.
const p = new Promise(resolve => {
console.log("I run immediately!");
resolve(1);
});Observables are Lazy
Nothing happens when you define an Observable. The code only runs when you call .subscribe().
const obs$ = new Observable(obs => {
console.log("I wait for subscription");
obs.next(1);
});Cancellability
Promises generally cannot be cancelled. Once fired, the request goes out. Observables, however, return a Subscription object. Calling .unsubscribe() on this object cancels the ongoing operation. This is critical in Single Page Applications (SPAs) to prevent memory leaks when a user navigates away from a component before an async task finishes.
Pro Tip: Angular'sHttpClientreturns Observables. Use theasyncpipe in your templates to handle subscription and unsubscription automatically!