In our app we have quite a few places where we use:
someObservable.take(1).subscribe(onSuccessHandler, onFailureHandler);
But with subscriptions you need to worry about unsubscribing at some point and that is not always straightforward.
I was thinking of simplifying this and rewriting this as:
someObservable.toPromise().then(onSuccessHandler).catch(onFailureHandler);
But looking at the implementation of toPromise()
(here) I don't seem to understand why it doesn't care about unsubscribing.
The comment in the code says that no cancellation could be done, but how we just leave it like this to leak memory (in case we actually are).
EDIT
I came up with an example that worries me:
Observable.timer(10, 10).toPromise().then((v) => console.log("I'm done"));
If observables I retrieve are such that they never complete, then not only my promises never complete with a value, but also I have no way to unsubscribe from such observables (e.g. time-out them and my promises), because I have no access to a subscription object. And that does leak memory!
Unsubscribing Manually RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .
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!
As mentioned here, these are the main reasons why toPromise is being deprecated: One goal was to remove it from the Observable prototype and turn it into a standalone util function. The naming of toPromise is not the best. Especially when used in combination with await it does not read very well: await categories$.
The RxJS first() operator waits until the first value is emitted from an observable and then automatically unsubscribes, so there is no need to explicitly unsubscribe from the subscription.
My guess is that it is because a promise is resolved only once (not like a sequence which is a stream). Note that the subscriber always keep the latest value, rejects on failure and resolves to the latest value on complete.
To try it for your self, try:
Observable.timer(300,300).take(4).toPromise().then((v) => console.log('tick: ', v)); // logs "3", the last element
Observable.from(['a','b','c']).toPromise().then((v) => console.log('tick: ', v)); // logs "c", the last element
As for unsubscribing, it is automatic on completion, so before completion, you shouldn't unsubscribe, on completion, you resolve the promise and silently (due to the default behavior of observables) unsubscribed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With