Blog

Observable vs Promise | What's the difference?

Key Takeaways

  • Promises are eager and always execute asynchronously.
  • Observables are lazy; they execute only when subscribed to and can be both synchronous and asynchronous.
  • RxJS introduces operators that simplify working with Observables.
  • Observables support multiple emissions and can be cancelled by unsubscribing; Promises cannot.

Eager vs Lazy

Promises initiate their work as soon as they are created. You don’t have control over when they start executing; they fire eagerly:

const myPromise = new Promise((resolve, reject) => {
  console.log('Promise firing!')
  resolve('Promise resolved.')
})
console.log('Before calling then...')
myPromise.then(res => console.log(res))

prints...

Promise firing!
Before calling then...
Promise resolved.

In contrast, Observables are lazy. They wait for something to subscribe before they begin execution:

import { Observable } from 'rxjs';
const myObservable$ = new Observable(observer => {
  console.log('Observable firing!')
  observer.next('Observable called')
});
console.log('Before calling subscribe on Observable')
myObservable$.subscribe({
  next: console.log
})

prints...

Before calling subscribe on Observable
Observable firing!
Observable called

Sync vs Async

Promises are inherently asynchronous—no matter how quickly they resolve:

const myPromise = new Promise((resolve, reject) => {
  resolve('Promise resolved.')
})
console.log('Before calling then...')
myPromise.then(res => console.log(res))
console.log('After calling then...')

prints...

Before calling then...
After calling then...
Promise resolved.

Observables can behave synchronously if they are designed to do so:

import { Observable } from 'rxjs';
const myObservable$ = new Observable(observer => {
  observer.next('Observable called')
});
console.log('Before calling subscribe')
myObservable$.subscribe({
  next: console.log
})
console.log('After calling subscribe')

prints...

Before calling subscribe
Observable called
After calling subscribe

You can easily make Observables asynchronous:

const myObservable$ = new Observable(observer => {
  setTimeout(() => {
    observer.next('Observable called')
  }, 1000)
});

Here, a setTimeout function delays execution, demonstrating that Observables can also operate asynchronously.

RxJs Operators

Observables aren’t natively built into JavaScript and instead utilize RxJS to provide a powerful library of operators and utility functions. With RxJS, you can manipulate streams of data easily:

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
const myObservable$ = new Observable(observer => {
  observer.next(2)
});
const mappedValues = myObservable$.pipe(map(x => x * 2));
mappedValues.subscribe({
  next: console.log
});

prints...

4

This example applies the map operator to transform emitted values, demonstrating the flexible data handling RxJS offers.

Cancellability

One unique advantage of Observables is their cancellability. By unsubscribing, you can halt the execution of Observables:

const subscription = myObservable$.subscribe();
subscription.unsubscribe();

Promises, once initiated, cannot be canceled. They complete irrespective of whether you still need the result.

Emitting Multiple Values

Observables can easily emit multiple values over time, which suits streaming data:

const myObservable$ = new Observable(observer => {
  observer.next(1)
  observer.next(2)
  observer.next(3)
});
myObservable$.subscribe({
  next: console.log
});

prints...

1
2
3

Promising a singular result, a Promise resolves once and finalizes:

const myPromise = new Promise((resolve, reject) => {
  resolve(1)
  resolve(2)
  resolve(3)
})
myPromise.then(res => console.log(res))

prints...

1

Only the first resolution is recognized by a Promise.

FAQ

When should I use Promises over Observables?

If you need a single asynchronous result or you’re primarily working with the Fetch API, Promises are likely sufficient and simpler to implement.

Which is better for real-time data?

For real-time data inflow, like WebSockets or event listeners, Observables are more appropriate because they can handle multiple asynchronous values.

Can I convert a Promise to an Observable?

Yes, you can wrap Promises with Observables using RxJS functions like from.

Are Observables replacing Promises in modern web development?

Not completely. Observables are preferred in applications needing complex asynchronous data handling, but Promises remain widespread due to their simplicity for single-result scenarios.

Mastering the tech interviewWhat everyone is doing wrong in tech interviews