Modernization

The issues of migration: Observables vs. Promises

Lucas Fievet
|
April 12, 2022

As a company that specializes in migrations, we understand the frustrations when it comes to the migration from AngularJS to Angular, especially when issues arising due to differences between Promises in AngularJS and Observables in Angular2+.

In this article, we would like to highlight the key differences between Promises and Observables and clear confusions that you may have.

Promises

Promises are commonly used in AngularJS to handle HTTP requests. After making a request, a single response is expected with which the promise is resolved as in the example below.

However, resolving a Promise again with a different value will not work. It is always resolved with the initial value passed to the resolve function and disregards next calls to it:

Observables

In contrast to Promises, Observables emit a stream of one or multiple values that are all passed to their subscribers as illustrated in the example below. Typically, the Angular HTTP service provides an Observable stream with one response value, making its behaviour alike to a Promise.

In basic migration scenarios, the AngularJS $http service can be replaced by the Angular httpService. However, if you are dealing with more complex applications there a many key differences to pay attention to. Hereafter, we will discuss the most common differences:

Eager vs. Lazy

In the example above, when you call the saveChanges method, the initial Promise-wrapped request will function. While Promises are eager-evaluated, Observable-wrapped requests will not do anything as Observables are lazy-evaluated.

Observables will be called only if you subscribe to them. In the previous case, the post Observable needs to be subscribed as follows for the http called to be executed:

Cancelling and unsubscribing

Let us have an example where on input text change from the user a search is requested on the backend. One major disadvantage is that you cannot reject the results of the initial request if you keep typing.

Although you can ease this problem with a debounce, it does not entirely resolve the problem. Further on, there is a possibility of race conditions, which means that an incorrect response will be displayed due to the later request result coming back before earlier requests.

An Observable eliminates this issue elegantly with the use of the switchMap operator:

In this example, the input text typing is converted to an observable value stream. Each time a new text value is being emitted, the switchMap operator will cancel the last network requests and send a new one, if the last one is not finished.

Repeat or Retry becomes so much simpler with Observables

Implementing a retry logic with Promises is a complex exercise that typically ends in a variation of the following code:

However, with Observables the same retry logic is implemented with the following one-liner!    

Observables have many combination tools that Promises miss

Promises only have two combination tools:

  • Promise.all
  • Promise.race

In contrast, Observables have a variety of combinations:

  • combineLatest(observable1, observable2,…)
  • observable1.pipe(withLatestFrom(observable2)
  • forkJoin(observable1, observable2,…)
  • zip (observable1, observable2,…)
  • race(observable1, observable2,…)
  • merge(observable1, observable2,…)
  • switchAll
  • concat

And so much more: window, switchMap, partition, groupBy, mergeMap, iif, etc.

Last words...

When you migrate from AngularJS that uses Promises to Angular2+ that uses Observables, you need to be careful about the differences between the two frameworks. In particular, Observables offer powerful combination tools that should be leveraged to simplify the codebase. We hope that this article was helpful to you and clarified differences that will ease your future developments or migration!

Hope you enjoyed today's #MondayBlog about Observable best practices and will have fun using the latest features! Stay tuned for the upcoming Angular news.


Related Blogs Posts

Bring your productivity to the next level

Reach the automation level you are aiming for

Leverage no-code and write custom code where needed

Visualize your end-user experience all in one place

Make your deployment decisions easy

Get Started