3
votes

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 ?

1
this.data = data ? data : undefined You surely mean this.data === data ? data : undefinedJeremy Thille
no this line is good, I affect dat object or undefined in this.dataghuntheur
Ok, I was just wondering whether it was a typo or not. I get it, it's actually this.data = (data ? data : undefined)Jeremy Thille
yes, it's that; I try to merge or concat subscribe but it does not workghuntheur
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.Jeremy Thille

1 Answers

17
votes

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();
  }
}