Subscriptions for an
Observable, like usual listeners, demand to be managed for avoiding a memory leak.
Ask yourself the following:
- How often do you take care to cancel your subscriptions?
- How many ways do you know to do that?
Let’s start discovering ways for completing the mission (double-meaning 😄 ).
The Declarative Approach
The declarative approach means that we use an operator to dispose the subscription for an
Observable. Right after the disposing - a completion event is emitted in order to notify us that the subscription has finished. We’re able to catch the event and respond respectively.
Now, we’re going to see several declarative operators.
The “first” Operator
An operator that emits the first value which passes the provided predicate. If a predicate isn’t provided, it emits the first value. Thereafter - it completes the subscription.
Take for an example the following:
We instantiate an
Interval of every second and emit the third value:
Pay attention that the completion event was fired.
The “last” Operator
An operator that emits the last value which passes the provided predicate. If a predicate isn’t provided, it emits the last value. Thereafter - it completes the subscription.
In fact, it’s a counterpart for the
Here’s an example:
We emit the last value that’s divided by 3 and lower than 25:
In like manner, the completion event was fired.
The “take” Operator
An operator that emits the nth values according to a provided number. Thereafter - it completes the subscription.
Here’s an example:
We emit the seventh values of a
mousemove event (notice we use
throttleTime operator in order to ease up our demonstration).
Try it yourself over the “Result” section:
As we guess, the completion event was fired.
The “takeWhile” Operator
An operator that emits the values until the provided predicate is false. Thereafter - it completes the subscription.
Here’s an example:
We define a local variable that’s called
isDone and used as the predicate. Then, we set up an
Observable that listens for the first click event on the “Stop” button. Once the click event is fired - the predicate will change to truthy value. Finally, we instantiate an
Interval of every second that emits each value until
isDone has truthy value.
Try it yourself by clicking on “Start counting” button inside “Result” section. Click on “Stop” button after a few moments:
Pay attention that completion event of the click listener has been fired before the
Interval completion event.
The “takeUntil” Operator
An operator that emits the values until a provided
Observable emits a value or finishes. Thereafter - it completes the subscription.
Take a look at an example with the previous behavior:
As it seems, a predicate isn’t needed anymore due to the fact that the first emitted click event will complete the
takeUntil takes an
Observable, therefore - that’s the reason for the
stop$ pointer for the sake of those objectives:
- Subscribing this pointer for its completion event.
- An emitter that indicates the
Intervalsupposed to be completed.
We expect to see the same result:
The Imperative Approach
The imperative approach means that we dispose the subscription for an
Observable manually and actually means it’s aborted and not completed.
The major advantage is the fact which the subscription is canceled immediately. However, we’d not be notified when the subscription is canceled. In addition, we’ll have to maintain an instance for each subscription. This instance lets us invoke
unsubscribe method of the subscription at moments we wish.
You can read more about the disadvantages of this approach here.
Let’s go back our example with the
Interval and the click event but with a few alterations:
Notice that we’ve a pointer for each subscription. Through those pointers, we’re able to access the subscriptions and
unsubscribe them directly.
We’re already familiar with the “Result” section and know how to operate it:
As we can see, after clicking on the “Stop” button - none of the completion events, that we’ve seen above, is invoked.
In this article we explored a couple of approaches to cancel a subscription for an
Observable. We started with the meaning of the declarative approach and a few operators which implement that approach. Afterwards, we comprehended the meaning of the imperative approach in contrast to the previous approach.