toPromise method is a method form Rxjs library, It is used to convert an observable to a promise.
The toPromise method subscribe to observable and retrun the last emitted value of that observable.
Let’s Understand toPromise Functionality with the example code
observable$ = new Observable <String> (Observer =>{
Observer.next("fistValue");
Observer.next("lastValue");
Observer.complete();
})
async function emmitValue(){
const value = await observable$.toPromise();
}
emmitValue();
//******Output is */
lastValue
So in the above code we are creating an observable which is emitting values one by one, but at the end it only emit one value whatever the last value is.
Also if you want more understanding of observables and promise you can checkout our this blog post
All looks fine right. What is the problem then?
Well the problem with toPromise is, it cannot handle undefined value properly.
Let’s understand what is the issue.
Problem with undefined in toPromise Method
First Problem is when you observable completes without returning the emitted value, for example in our above code the last emitted value which is returning is “lastValue”. so in case when there is no last emitted value and observable only execute complete then the output will be undefined.
Example code for Frist Problem
observable$ = new Observable <String> (Observer =>{
Observer.complete();
})
async function emmitValue(){
const value = await observable$.toPromise();
}
emmitValue();
//******Output is */
undefined
So in the above code we are not returning any value, now the observable converting with toPromise return a value of undefined.
Now the Second Problem is, what if you pass undefined as a value inside the observer.next, So the value we are passing is undefined and the toPromise will also return undefined, so now how we will handle this situation that the value we are getting as undefined is actually a value which is passed by observable or there is no value passed from the observable.
Example code for Second Problem
observable$ = new Observable <String> (Observer =>{
Observer.next(undefined);
Observer.complete();
})
async function emmitValue(){
const value = await observable$.toPromise();
}
emmitValue();
//******Output is */
undefined
This was the main reason to deprecate the toPromise from the Rxjs library.
Alternative To Resolve this toPromise undefined issue
When you convert observable into toPromise you might want to select only first value or may be last value. May be you don’t want to wait for observable to complete and you just want the first value whatever it is coming inside observable.
Now to handle these undefined values, toPromise is deprecated and two other methods were introduced.
firstValueFrom Method
It returns first value emitted by the observable, subscription will released immediately after returning the value. It means once the first value occur the subscription to that observable finish.
Also it will reject with an Empty Error if the observable complete with no value or undefined value.
observable$ = new Observable <String> (Observer =>{
Observer.next("FirstValue");
Observer.next("SecondValue");
Observer.complete();
})
async function emmitValue(){
const value = await firstValueFrom(observable$,{defaultValue:'to replace empty value'})??'to replace undefined'
}
emmitValue();
//******Output is */
"FirstValue"
So now in above code we can see that firstValueFrom method takes the observable value and check for empty and undefined value and we can use default value in case if the observable return empty value and we can use another value after ?? if the value returns undefined.
This way we can handle the empty and undefined values.
lastValueFrom Method
Simmilar way lastValueFrom returns last emitted value and check for empty value and undefined value. lastValueFrom also stops the subscription once the last value is emitted.
Example code is also similar but the output is different. Output is last emitted value.
observable$ = new Observable <String> (Observer =>{
Observer.next("FirstValue");
Observer.next("SecondValue");
Observer.complete();
})
async function emmitValue(){
const value = await lastValueFrom(observable$,{defaultValue:'No Value'})??'Third Value in place of undefined'
}
emmitValue();
//******Output is */
"LastValue"
Now understand the empty value. So in our first problem example code we were not returning any value and we completed the observable.
observable$ = new Observable <String> (Observer =>{
Observer.complete();
})
Now the empty value is passing to the firstValueFrom and lastValueFrom, these method will now give the output as undefined.
In case of these two methods the output will throw an error.
Error : no element in seqence
So this is how toPromise issue of undefined is resolved by the firstValueFrom and lastValueFrom methods.
If you like this blog please share it with your friends and also comment if you have any doubt or suggestion.