Angular 5 subscribe and unsubscribe Observable

27,105

Behavior Subject, Subscribe & Unsubscribe Observables

Behavior subjects are very useful while sharing data in multiple components. You can subscribe them as many times as you want. Also you can unsubscribe it using unsubscribe method.

Let's take the above service and subscribe that service to get data:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class DataService {
    public source = new BehaviorSubject<any>(' ');
    data = this.source.asObservable();
    constructor() { }
    update(values: any) {
        this.source.next(values);
    }
}

Here, I have declared a behavior subject with initial value empty string. Just remember that you need to give a default value to your behavior subject whether it a blank string or any number. After that, I have initialized an observable data using asObservable() method. And finally, I have created a method which updates the behavior subject source value using next() method.

Now I will use this Service in our component to get data from our behavior subject.

subscription: any;

constructor( private dataSvc: DataService ) {
    this.subscription = this.dataSvc.data.subscribe(
        data => console.log('Data:', data),
        err => console.log(err),
        () => console.log('complete')
    );
}

Here I have injected our DataService to our component and I have created an instance of that DataService dataSvc. I have used dataSvc to call our data observable and subscribe that data observable to get data from our behavior subject. So the output which I will get in the browser console by the following code is:

Data: 

So I am getting this empty because I have used an empty string as the default value for my behavior subject.

Now to update the value of behavior subject, I have to use update method of dataSvc service which will update the value of BehaviorSubject for the empty string to the new value.

//Insert this before subscribing the data observable
this.dataSvc.update('abc');

//Output in the console.
Data: abc

Now the value has been updated from empty string to abc. And this will reflect in each and every component where are subscribing this BehaviorSubject.

So what if I want to unsubscribe this subscription. So we have to initialize subscription as

subscription: ISubscription;

and then whenever we want to unsubscribe we will call unsubscribe method of ISubscription like this

this.subscription.unsubscribe();

So the complete code for a particular component will be like this:

import { Component } from '@angular/core';
import { DataService } from "./data.service";
import {ISubscription} from "rxjs/Subscription";


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  subscription: ISubscription;

  constructor( private dataSvc: DataService ) {
    this.subscription = this.dataSvc.data.subscribe(
      data => console.log('Data:', data),
      err => console.log(err),
      () => console.log('complete')
    );
    this.dataSvc.update('abc');
    this.subscription.unsubscribe();
  }
}
Share:
27,105
ghuntheur
Author by

ghuntheur

Front-end developer

Updated on February 02, 2020

Comments

  • ghuntheur
    ghuntheur about 4 years

    I have to get datas from two subscribe but I get always data of the first one.

    I have a data shared service :

    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs/BehaviorSubject';
    
    
    @Injectable()
    export class DataService {
    
        private source = new BehaviorSubject<any>('');
        data = this.source.asObservable();
    
        constructor() { }
    
        update(values: any) {
            this.source.next(values);
        }
    }
    

    Before leaving search component, I call update method.
    Now, I'm on the results component. I get shared data like that :

    constructor(private dataSvc: DataService,
            private router: Router,
            private rideStore: RideStore) { }
    
        ngOnInit() {
            this.getData();
        }
    
        getData() {
            this.subscription = this.dataSvc.data.take(1).subscribe(
                data => this.data = data ? data : undefined,
                err => console.log(err),
                () => this._isValid()
            );
        } 
    

    My question is : I need shared data to subscribe to another observable. First, I construct an object ride and after i call the search method

        search() {
        this.rideStore.searchRides(this.ride).subscribe(
            rides => {
                // this.dataSvc.update(rides);
                this.rides = rides;
                console.log('results', this.ride);
            },
            err => console.log('err', err)
        );
    }
    

    The problem is I always get data from data service and not from the api call. The api works cause I intercept results in store but not in the component. So How I can stop subscribing first observable and subscribe of the second ?

    • Jeremy Thille
      Jeremy Thille about 6 years
      this.data = data ? data : undefined You surely mean this.data === data ? data : undefined
    • ghuntheur
      ghuntheur about 6 years
      no this line is good, I affect dat object or undefined in this.data
    • Jeremy Thille
      Jeremy Thille about 6 years
      Ok, I was just wondering whether it was a typo or not. I get it, it's actually this.data = (data ? data : undefined)
    • ghuntheur
      ghuntheur about 6 years
      yes, it's that; I try to merge or concat subscribe but it does not work
    • Jeremy Thille
      Jeremy Thille about 6 years
      I don't really know. It sounds easy to make two subsciptions, doesn't it? Like this.sub1 and this.sub2 and just have two subs.
    • ghuntheur
      ghuntheur about 6 years
      It's my code actually........
    • Jeremy Thille
      Jeremy Thille about 6 years
      What? What do you mean it's your code? I know it's your code :^)
    • Jeremy Thille
      Jeremy Thille about 6 years
      Oh, I get it. You mean, it's my code currently? I suspect you're French? wordreference.com/enfr/actually - Anyway, yes, there are two subs, it's just that you don't give a name to the second one. I don't know either why it's not working. But if you want to unsubscribe to the first one, just do this.subscription.unsubscribe()
    • ghuntheur
      ghuntheur about 6 years
      I had a little mistake. Now it works. Thanks