October 17, 2019

Create Custom Observable in Angular

Observable in Angular are object imported from a third party package called Rxjs that act as a wrapper around a data source which are received asynchronously mostly via HTTP calls.

Create custom observable in angular

In this article we will create a simple custom observable in Angular 8 to understand the basic workflow and steps involved in sending and receiving data.

Once you create an observable in Angular, it requires subscriber who subscribes to listen changes and act upon it. The subscriber here will be angular client which will have three methods at is disposal. One each for handling the incoming data, errors and completion.

Create Custom Observable

Let us head over to our app.component.ts file and start creating our first observable. Observable sends data asynchronously, so here will create one which sends some text after a interval of 2 seconds.

import { Component, OnInit } from '@angular/core';
import {Observable, Observer} from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'custom-observable';

  ngOnInit(){
    const customObservable = Observable.create(
      (observer : Observer<string>) => {
       
       setTimeout(
         () => {
           observer.next("I will be received after 2 sec");
         }, 2000); 
   
       setTimeout(
         () => {
           observer.next("I will be received after 4 sec");
         }, 4000); 
       
       setTimeout(
         () => {
           observer.next("I will be received after 6 sec");
         }, 6000); 
   
       setTimeout(
         () => {
           observer.complete();
         }, 8000); 
   
      } );
  } 
}
 
  • Firstly we will import Observable and Observer
  • The create method, used to create an observable expects a asynchronous function as a parameter. This async function further takes in a parameter of type Observer<data-type>. This is the actual data-type which the observable will return.
  • Next() method will emit the actual data. It is used inside the setTimeout() function to replicate the delay for 2 seconds while receiving data.
  • The Complete() method indicates the end of observable and no further data is returned by the observable post the complete method.
  • We will receive three sets of data here each after 2 secs and post that our observable will end.

Also Read: Create a custom Pipe in Angular 8

Now lets us create a subscriber which will get the data from customObservable.

Create the Subscriber

customObservable.subscribe(
      (data:string) => {
        console.log(data);
      },

      (error:string) => {
        console.log("I will handle the observable errors");
        console.log(error);
      },

      ()=> {
        console.log("I will be called when the observable is completed");
      }
      
    )
  • The subscribe method is used to subscribe to an observable in angular.
  • It can accept three anonymous functions as parameter, each to handle the three use cases.
  • The first parameter is a function which handles the actual data. Here we are simply logging it in our console for the demo purpose
  • The second parameter is a function taking in the error returned as a parameter
  • The third parameter is again a method with no parameter, which is called when the observable completes its processing.

Head over to the browser and see the application in action.

Observable-Result-in-Angular

Note: All the messages will be logged after a interval of 2 sec each, as defined in the setTimeout() method.

Let us now update our observable to generate some error and see how it can be handled by the subscriber.

const customObservable = Observable.create(
      (observer : Observer<string>) => {
       
       setTimeout(
         () => {
           observer.next("I will be received after 2 sec");
         }, 2000); 
   
       setTimeout(
         () => {
           observer.next("I will be received after 4 sec");
         }, 4000); 
       
       setTimeout(
         () => {
           observer.next("I will be received after 6 sec");
         }, 6000); 

        setTimeout(
          () => {
            observer.error("Opps something went at 7 sec wrong and now the completed method will not be called");
          }, 7000); 
   
       setTimeout(
         () => {
           observer.complete();
         }, 8000); 
   
      } );

Note: The method to handle the completion of our observable will not be called as the error handles kicks in before the observable is completed.

Error-in-Observable

Practically rarely will be in need to implement our own observable, and mostly we will use the once provided by Angular.

But a custom implementation will give you a brief idea what actually happens behind the scenes with the observable.

There are also various operators like “Map, GroupBy” etc. which can be used to transform the data from the observable before each reaches the subscriber. You can know more about them in detail in the official documentation.

Her’s the complete code of the app.component.ts file used in the tutorial.

import { Component, OnInit } from '@angular/core';
import {Observable, Observer} from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'custom-observable';

  ngOnInit(){
    const customObservable = Observable.create(
      (observer : Observer<string>) => {
       
       setTimeout(
         () => {
           observer.next("I will be received after 2 sec");
         }, 2000); 
   
       setTimeout(
         () => {
           observer.next("I will be received after 4 sec");
         }, 4000); 
       
       setTimeout(
         () => {
           observer.next("I will be received after 6 sec");
         }, 6000); 

        setTimeout(
          () => {
            observer.error("Opps something went at 7 sec wrong and now the completed method will not be called");
          }, 7000); 
   
       setTimeout(
         () => {
           observer.complete();
         }, 8000); 
   
      } );

    customObservable.subscribe(
      (data:string) => {
        console.log(data);
      },

      (error:string) => {
        console.log("I will handle the observable errors");
        console.log(error);
      },

      ()=> {
        console.log("I will be called when the observable is completed");
      }
      
    )

  } 
}
 

Leave a Reply

Your email address will not be published. Required fields are marked *