Author avatar

Yallaling Goudar

Subscribing to and Unsubscribing from Observables

Yallaling Goudar

  • Aug 16, 2019
  • 7 Min read
  • 40 Views
  • Aug 16, 2019
  • 7 Min read
  • 40 Views
Languages Frameworks and Tools
Angular

Introduction

Observables have very useful benefits like event handling, asynchronous programming, and handling multiple values. Observables are useful in passing messages between publishers and subscribers in your application. Observables are declarative and we can define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe. An observable can deliver multiple values of different types like literals, messages, or events, depending on the context. The API for receiving values is the same whether the values are delivered synchronously or asynchronously.

Using Observables

To execute the observable, we have to create and begin receiving notifications. To do this, you call its subscribe() method, passing an observer. An observer is a JavaScript object that defines the handlers for the notifications you receive. The subscribe() call returns a Subscription object that has an unsubscribe() method, which you call to stop receiving notifications. Now let’s consider an example of how we can create an Observable that will start listening to geolocation updates. When the consumer subscribes we will get the next and error callbacks. A simple geolocation API check provides values to publish. When the consumer unsubscribes, clean up data ready for the next subscription. Then we will call subscribe() to start listening for updates. And Stop listening to the location after 10 seconds.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const locations = new Observable((observer) => {
  const {next, error} = observer;
  let watchId;
 
  if ('geolocation' in navigator) {
	watchId = navigator.geolocation.watchPosition(next, error);
  } else {
	error('Geolocation not available');
  }
 
  return {unsubscribe() { navigator.geolocation.clearWatch(watchId); }};
});
 
const locationsSubscription = locations.subscribe({
  next(position) { console.log('Current Position: ', position); },
  error(msg) { console.log('Error Getting Location: ', msg); }
});
 
setTimeout(() => { locationsSubscription.unsubscribe(); }, 10000);
typescript

Notification Types in Angular

The observer interface is implemented by a handler for receiving observable notifications. It is an object that defines callback methods to handle the three types of notifications that an observable can send, as shown below.

Notification Types:

  • next: It is a required notification type. A handler for each delivered value. Called zero or more times after execution starts.
  • error: It is an optional notification type. A handler for error notification. An error halts the execution of the observable instance.
  • complete: It is an optional notification type. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.

Subscribing to Observables in Angular

An Observable instance begins publishing values only when someone subscribes to it. We can subscribe by calling the subscribe() method of the instance which passes an observer object to receive the notifications. Now let’s see how subscribing works, we need to create a new observable. While there is a constructor that you use to create new instances, for illustration, we can use some methods from the RxJS library that create simple observables of frequently used types:

  • of(...items): It returns an Observable instance that synchronously delivers the values provided as arguments.
  • from(iterable): It converts its argument to an Observableinstance. This method is commonly used to convert an array to an observable. Now let’s consider an example of creating and subscribing to a simple observable, with an observer that logs the received message to the console. In the below example we are creating a simple observable that emits three values.

Subscribe Using an Observer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const newObservable = of(1, 2, 3);
 
const newObserver = {
  next: val => console.log(newObserver got a next value: ' + val),
  error: err => console.error(newObserver got an error: ' + err),
  complete: () => console.log(newObserver got a complete notification'),
};
 
newObservable.subscribe(newObserver);
// Output:
// newObserver got a next value: 1
// newObserver got a next value: 2
// newObserver got a next value: 3
// newObserver got a complete notification
typescript

The subscribe() method can also accept the callback function definitions inline, for next, error, and complete handlers. For example, the following subscribe() call is the same as the one that specifies the predefined observer.

Subscribe with Positional Arguments

1
2
3
4
5
newObservable.subscribe(
  val => console.log(newObserver got a next value: ' + val),
  err => console.error(newObserver got an error: ' + err),
  () => console.log(newObserver got a complete notification')
);
typescript

Two Subscriptions in Observables

If we use subscribe twice, there will be two separate streams, each emitting values every second. Let’s look at the example below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Subscribe starts the clock, and will emit after 1 second
sequence.subscribe({
  next(num) { console.log('1st subscribe: ' + num); },
  complete() { console.log('1st sequence finished.'); }
});
 
// After 1/2 second, subscribe again.
setTimeout(() => {
  sequence.subscribe({
	next(num) { console.log('2nd subscribe: ' + num); },
	complete() { console.log('2nd sequence finished.'); }
  });
}, 500);
 
// Outputs:
// (at 1 second): 1st subscribe: 1
// (at 1.5 seconds): 2nd subscribe: 1
// (at 2 seconds): 1st subscribe: 2
// (at 2.5 seconds): 2nd subscribe: 2
// (at 3 seconds): 1st subscribe: 3
// (at 3 seconds): 1st sequence finished
// (at 3.5 seconds): 2nd subscribe: 3
// (at 3.5 seconds): 2nd sequence finished
typescript

Unsubscribing or Canceling an Observable in Angular

We can unsubscribe or cancel an Observable. Canceling or unsubscribing removes the listener from receiving further values and notifies the subscriber function to cancel work. Let’s see an example below where we are listening for the button click event. When we first subscribe to the event, it will begin listening. When we want to stop listening, we will unsubscribe to the subscription.

1
2
3
4
5
6
7
8
9
// Setup
let clicks$ = fromEvent(buttonElement, ‘click’);
 
// Begin listening
let subscription = clicks$
  .subscribe(e => console.log(‘Clicked’, e))
 
// Stop listening
subscription.unsubscribe();
typescript

Conclusion

In this guide, we have explored reactive form validations in Angular. We have also seen how we can build or create a custom reactive form validation and use it in our application. You can learn more about Angular Reactive Forms validations in my guide Validating Reactive Forms in Angular.

2