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>;
}
<>
this: Observable<T>
: Type declaration of the this
parameter which is describing the expected type of the implicit this
object.this
context without noticing it.promiseCtor
is a Promise constructor - enabling us to use it with different Promise
implementations.subscribe
call in a Promise
which will resolve
when the Observable
’s complete
handler is called.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