Observables are distinctive and powerful functions which some of us apply on a daily basis. Today, we're going to discover a several ways in RxJS to cancel them.

Motivation

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 first operator.

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 Interval . takeUntil takes an Observable , therefore - that’s the reason for the stop$ pointer.

We use stop$ pointer for the sake of those objectives:

Subscribing this pointer for its completion event.

An emitter that indicates the Interval supposed 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.

Conclusion

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.