83

I have read that toPromise() is being deprecated in RxJS 7 and will be removed in RxJS 8. I have often used it with async await syntax in angular to handle http calls. Is it considered an anti pattern? I understand the concept of streams but an http call only emit a single value. I don't get the point of observable for a simple http call. What should I use next? should I fully embrace reactive programming?

Matias
  • 1,070
  • 2
  • 6
  • 14
  • 1
    As is conventional, the alternatives are provided in the deprecation: https://github.com/ReactiveX/rxjs/commit/aa9ab6b555203529a699b3a79531a57b7d78fefa – jonrsharpe Apr 11 '21 at 11:23

3 Answers3

110

Why is this happening?

As mentioned here, these are the main reasons why toPromise is being deprecated:

  1. One goal was to remove it from the Observable prototype and turn it into a standalone util function.

  2. The naming of toPromise is not the best. Especially when used in combination with await it does not read very well: await categories$.toPromise() vs await lastValueFrom(categories$)

  3. The type information of toPromise is wrong. When the source Observable completed without ever emitting a single value - it resolved with undefined. It should reject in that case. A Promise is a "promise" that when it resolves a value will be there - and be it undefined. But when the stream completes without ever emitting a value you can't differentiate between a stream that a emitted undefined on purpose and a stream that completed without ever emitting anymore

What should you use next?

If you really insist doing it the promise way, lastValueFrom/firstValueFrom. Otherwise switching to reactive programming would be the way to go.

Using toPromise ( deprecated ) -

public async loadCategories() {
    this.categories = await this.inventoryService
      .getCategories()
      .toPromise()
}

Using lastValueFrom ( new ) -

import { lastValueFrom } from 'rxjs';

public async loadCategories() {
    const categories$ = this.inventoryService.getCategories();
    this.categories = await lastValueFrom(categories$);
} 

This link should help -

https://indepth.dev/posts/1287/rxjs-heads-up-topromise-is-being-deprecated

Pawan Sharma
  • 1,842
  • 1
  • 14
  • 18
28

firstValueFrom and lastValueFrom is definitly a better alternative for many reasons:

  1. The naming is more readable and self explanatory.
  2. The additional ability to select either first or last value.
  3. The additional ability to declare a default value in case the observable didn't emit any value at all like so await lastValueFrom(data$, {defaultValue: 'Some default value'})

For more about this checkout the video below:
https://www.youtube.com/watch?v=3aeK5SfWBSU

Tariq Saeed
  • 1,154
  • 1
  • 10
  • 15
21

Code example:

Deprecated use:

await this.http.post<boolean>(`/someApi`).toPromise()
  .then((value) => {
    console.log(`Result: ` + value);
  })

New code:

import { firstValueFrom } from 'rxjs';

await firstValueFrom(this.http.post<boolean>(`/someApi`))
  .then((value) => {
    console.log(`Result: ` + value);
  })
Khabir
  • 5,370
  • 1
  • 21
  • 33
Adir Dayan
  • 1,308
  • 13
  • 21