2

Sometimes subscribing in a component, rather than using an async pipe is needed.

In these cases when only one value will ever be emitted by the observable, is there any reason or downside to converting to a promise? Since we are not subscribing, wouldn't this be safer than possibly having a memory leak if someone doesn't unsubscribe?

atotalnoob
  • 249
  • 2
  • 16
  • 1
    If you're observable only emits one and only one value, then it will complete and in this case, you don't need to unsubscribe. You can also use the "first" operator to take the first value, then unsubscribe. – ssougnez Aug 25 '20 at 16:30
  • 2
    To add to ssougnez comment, if your observable doesn't complete, then your promise would hang indefinitely, which is another caveat. There isn't really any beenefit of wrappign this in a Promise, excepted if you as a developper feel more confortable with it, or if some external lib / api requires it. – Pac0 Aug 25 '20 at 16:32
  • If you're talking about http requests see [Angular Http - toPromise or subscribe](https://stackoverflow.com/q/39265534/9423231). Also [Converting Observable to Promise](https://stackoverflow.com/q/52257515/9423231) – frido Aug 25 '20 at 17:23
  • But if I am using the first operator, I still have to unsubscribe. – atotalnoob Aug 25 '20 at 17:52
  • You only have to unsubscribe from an observable that completes when you want to cancel the observable before it completes. `toPromise` doesn't unsubscribe from the observable for you. It subscribes and then just waits for the observable to complete. Using `first` causes the observable to complete. So in regard to unsubscribing it's no different than using `toPromise`. – frido Aug 25 '20 at 19:59

1 Answers1

3

The downside I am aware of is that toPromise() is going to be deprecated in rxjs 7 and removed in rxjs 8. If you use it a lot now it will require extra work to migrate later. If you want have your code future proof in 6.x, implement lastValueFrom and firstValueFrom now, and use them, then it would be easy later to change the implementation provided in rxjs7 and removing those two methods. See the linked article for their usage.

import { Observable } from 'rxjs';
import { first } from 'rxjs/operators';

export function lastValueFrom<T>(obs$: Observable<T>): Promise<T> {
  return obs$.toPromise();
}

export function firstValueFrom<T>(obs$: Observable<T>): Promise<T> {
  return obs$.pipe(first()).toPromise();
}
Sherif Elmetainy
  • 4,034
  • 1
  • 13
  • 22