Conversión a Promesas
La similitud entre Observables y Promesas radica en que ambas colecciones pueden producir valores a lo largo del tiempo, pero la diferencia es que los Observables pueden producir ningún, o más de un valor, mientras que las Promesas producen un único valor cuando se resuelven con éxito.
Problemas
Por esta razón, en RxJS 7, el tipo de retorno del método toPromise()
se ha modificado para reflejar mejor el hecho de que los Observables pueden producir cero valores. Esto puede suponer un breaking change para algunos proyectos, ya que el tipo de retorno se ha cambiado de Promise<T>
a Promise<T | undefined>
.
Además, el nombre del método toPromise()
nunca indicaba cuál de los valores emitidos por el Observable sería el que tomaría la Promesa al resolverse, ya que los Observables pueden emitir múltiples valores a lo largo del tiempo. Al convertir a una Promesa, quizá se quiera elegir qué valor elegir - si el primer valor que haya llegado, o el último. Para solucionar estos problemas, se decidió que el método toPromise
pasaría a estar obsoleto, y se introducieron dos nuevas funciones helper para la conversión a Promesas.
Also, toPromise()
method name was never indicating what emitted value a Promise will resolve with because Observables can produce multiple values over time. When converting to a Promise, you might want to choose which value to pick - either the first value that has arrived or the last one. To fix all these issues, we decided to deprecate toPromise(), and to introduce the two new helper functions for conversion to Promises.
Las dos nuevas funciones
Para reemplazar el método toPromise()
obsoleto, se debe utilizar una de las dos funciones estáticas de conversión firstValueFrom
or lastValueFrom
.
lastValueFrom
lastValueFrom
es prácticamente igual que toPromise()
. Esto quiere decir que se resolverá con el último valor que haya llegado cuando el Observable se complete, pero con una diferencia en su comportamiento cuando el Observable se complete sin emitir ningún valor. En este caso, toPromise()
se resolvía con éxito con undefined
, mientras que lastValueFrom
se rechazará con EmptyError
. De esta menera, el tipo de retorno de lastValueFrom
es Promise<T>
, al igual que toPromise()
en RxJS 6.
Ejemplo
firstValueFrom
Sin embargo, quizá se quiera obtener el primer valor que llegue sin esperar a que el Observable se complete. En este caso se puede utilizar firstValueFrom
. firstValueFrom
se resolverá a una Promesa con el primer valor que haya emitido el Observable, y cancelará la suscripción automáticamente para retener recursos. firstValueFrom
también se rechazará con un EmptyError si el Observable se completa sin emitir ningún valor.
Ejemplo
Ambas funciones devolverán una Promesa que se rechazará si se produce un error en el Observable fuente. La promesa se rechazará con el mismo error que haya ocurrido en el Observable.
Uso del valor por defecto
Si no se desea que las Promesas creadas por lastValueFrom
o firstValueFrom
se rechacen con EmptyError en el caso de que no se emita ningún valor antes de que el Observable se complete, se puede utilizar el segundo parámetro. Este segundo parámetro dbe ser un objeto con un parámetro defaultValue
. El valor en defaultValue
se utilizará para resolver la Promesa si el Observable fuente se completa sin emitir ningún valor.
Advertencia
Solo se debe utilizar la función lastValueFrom
si se tiene la certeza de que el Observable fuente se acabará completando. La función firstValueFrom
se debe utilizar si se tiene la certeza de que el Observable fuente emitirá al menos un valor, o se acabará completando. Si el Observable fuente no se completa, ni emite ningún valor, se puede obtener una Promesa que esté colgada, y potencialmente todo el estado de una función asíncrona acabaría colgando en memoria. Para evitar esta situación, se puede utilizar timeout, take, takeWhile, o takeUntil, entre otros.
Last updated