JavaScript Theory: Promise vs Observable

The RxJS is currently by far the hottest JavaScript library, which is widely used especially in Angular single page applications. When you are first introduced to the library and the notion of the Observable, you may hear that it’s the Promise with multiple values or an asynchronous collection of data. However, the aforementioned definitions are not exact and I will cover the main differences in this blog post.

Eager vs Lazy

The first difference is that the Promise is eager, whereas the Observable is lazy.

The Promise is eager, since the executor function (passed as the constructor argument) gets invoked at the moment of its definition. The time when the then method is called doesn’t impact on the executor function:

In contrast, the Observable is lazy, since the producer function does not get called until you subscribe to the stream:

If you prefer to work with observables, you can convert a Promise object into an Observable instance using the from function:

Note that it does not prevent the Promise executor function from being invoked immediately. If you want to delay the moment of the function’s execution until you subscribe to the resulting stream (wrapping a Promise object), you need to make use of the defer function:

Async vs Sync

Even if immediately resolved, the Promise is always asynchronous. As a result, the then method’s callback will be added to the microtasks queue which will be processed after the current macrotask completion:

The Observable may be asynchronous:

or synchronous:

The behavior depends on the body of the producer function. In addition, some built-in streams can be created in both variants:

asynchronous

synchronous

Single vs Multiple values

The Promise object may only deliver a single value, namely the first call of the resolve function is taken into account:

In contrast, the Observable instance may emit multiple values:

If you want to release resources when they are no longer needed (in order to prevent from memory leaks), you need to return a callback function containing the teardown logic, which will be invoked once the stream has been unsubscribed:

Operators

The most astonishing feature of the RxJS library is a great number of built-in operators that can be applied to the Observable in order to get a new tailored stream. For example, you can handle race conditions in a nifty way:

The built-in switchMap operator takes care of unsubscribing from the pending inner observable once the data it provides is stale. The Promise cancellation is not that straightforward, since you need to make use of the AbortController or track if a resolved Promise object should be considered or not.

Conclusions

In a nutshell, the main differences between the Promise and the Observable are as follows:

  • the Promise is eager, whereas the Observable is lazy,
  • the Promise is always asynchronous, while the Observable can be either asynchronous or synchronous,
  • the Promise can provide a single value, whereas the Observable is a stream of values (from 0 to multiple values),
  • you can apply RxJS operators to the Observable to get a new tailored stream.

Live example:

I hope you liked the post and learned something new 👍. If so, please give me some applause 👏

JavaScript everyday

Improve your JavaScript skills everyday!