AngularJS(Angular 1) was using Promises heavily for HTTP calls, while Angular 2+ has network calls wrapped in Observables. This caused that some devs met specific issues while migrating projects from AngularJS to Angular 2+. I want to address these issues here and describe why they can appear at all by reviewing typical differences between Observables and Promises.

Observables — more capabilities for web-devs. (pic by mediamodifier)

Pre-requisites: you should know JS Promises

Observables and Promises — short intro

At first glance — Observables are just advanced Promises: Promises emits one value and complete (resolve), Observables emit 0, one or many values and complete as well (emit and complete are different actions). For HTTP service in AngularJS and Angular provides only one value — so seems both frameworks work very similar in this case.

And one may think that it is enough just rename $http to this.httpService, then to subscribe and everyone will be happy. In very simple apps it even can work — but if you application is doing something more then ‘Hello world’ — plz pay attention to these differences.

#1 Eager vs Lazy

Take a look at example below:

When I call saveChanges method — the first example with Promise-wrapped request will work as expected. But in seconds Observable-wrapped example nothing will happen because Observables are lazy-evaluated while Promises are eager-evaluated.

This means that Promises doesn’t care whether they have some subscribers to get their result or not. But Observables (to be precise — cold Observable) will be cold only if we subscribe to them. In the case above you should subscribe to Observable returned by saveChanges function.

saveChanges(data).subscribe()

To keep an eye on it — use rxjs-no-ignored-observable rule from rxjs-tslint-rules by Nicholas Jamieson.

#2 Promises cannot be canceled while Observables can be unsubscribed

Again, start with example when on input text change we do search on a back-end:

What is a drawback here — that you cannot reject results of the previous request if the user continues typing (debounce make this problem a bit less but doesn’t eliminate it). And one more issue — race condition is possible (when later request result will come back faster then earlier one — so we get incorrect response displayed).

Observable can avoid this concern quite elegant with switchMap operator:

Here we convert input text typing to observable values emissions. Each time new text value is emitted switchMap operator will cancel previous network request (if it is not finished yet) and send a new one.