RxJS heads up: toPromise is being deprecated

In RxJS 7 toPromise will become deprecated and with RxJS 8 it will be gone! So avoid using toPromise in your future development when possible.

In RxJS 7 toPromise will become deprecated and with RxJS 8 - it will be gone! This is a heads up that tries to prepare you for this breaking change.

What can we use instead?

In short: lastValueFrom or firstValueFrom - but read on to get the full picture.

In case you have missed it: Currently most of us are enjoying our reactive ride on RxJS 6, but** RxJS 7** is already available as a beta version.

Before RxJS 6 and the introduction of pipe-able operators we could have mistaken toPromise as an operator, but - it is not.

It can’t be used within the pipe function.

The toPromise function lives on the prototype of Observable and is a util method that is used to convert an Observable into a Promise.

Inside this function we subscribe to the Observable and resolve the Promise with the last emitted value - attention - when the Observable completes!

  toPromise<T>(this: Observable<T>): Promise<T>;
  toPromise<T>(this: Observable<T>, PromiseCtor: typeof Promise): Promise<T>;
  toPromise<T>(this: Observable<T>, PromiseCtor: PromiseConstructorLike): Promise<T>;
  toPromise(promiseCtor?: PromiseConstructorLike): Promise<T> {
    promiseCtor = getPromiseCtor(promiseCtor);

    return new promiseCtor((resolve, reject) => {
      let value: any;
      this.subscribe((x: T) => value = x, (err: any) => reject(err), () => resolve(value));
    }) as Promise<T>;
  }
<>

toPromise Source

  • this: Observable<T>: Type declaration of the this parameter which is describing the expected type of the implicit this object.
  • This is a so-called fake parameter - which only exists at compile time - to avoid bugs when you pass a function around and change its this context without noticing it.
  • promiseCtor is a Promise constructor - enabling us to use it with different Promise implementations.
  • The important part: We are then wrapping the the subscribe call in a Promise which will resolve when the Observable’s complete handler is called.

Examples#

When it comes to Angular most of you will be familiar dealing with Observables when we make HTTP requests using the built in HttpClient from Angular:

@Injectable({
  providedIn: 'root'
})
export class InventoryService {
  constructor(private httpClient: HttpClient) {}

  getCategories(): Observable<Category[]> {
    const url = 'https://www.themealdb.com/api/json/v1/1/categories.php';

    return this.httpClient.get<CategoriesResponse>(url).pipe(
      map(response => response.categories)
    );
  }
}
<>

Example of making a HTTP-Request returning a Observable

Usage of the “old” toPromise

When we don’t want to deal with a Observable in our component then we can currently use toPromise:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {
  categories: any[];

  constructor(private inventoryService: InventoryService) {}

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

Example using toPromise

**Usage of the “new” **lastValueFrom:

From a functional perspective lastValueFrom is the function we should go for as replacement of toPromise.

import { lastValueFrom } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {
  categories: any[];

  constructor(private inventoryService: InventoryService) {}

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

#rxjs #reactive-programming #promise #topromise

RxJS heads up: toPromise is being deprecated
47.25 GEEK