Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why RxJS function toPromise is not unsubscribing from subscription

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!

like image 204
eddyP23 Avatar asked Oct 06 '16 15:10

eddyP23


People also ask

Does RxJS take unsubscribe?

Unsubscribing Manually RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .

Does Observable toPromise subscribe?

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!

Why toPromise is deprecated?

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$.

Does RxJS first unsubscribe?

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.


1 Answers

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.

like image 146
Meir Avatar answered Oct 05 '22 22:10

Meir