Can I subscribe Observable from service provider?


#1

Hello guys. I have one question to ask. I’m kinda new to Ionic so I wonder whether I could subscribe observable from service or not. If so, how can I unsubscribe it when the user signs out from my application?

This is my user service provider.

user-service.ts

 getCurrentUsername() {
    return this.afDB.object(`users/${this.currentUserId}/username`).valueChanges();
  }

sendFriendRequest(recipient: string) {
    let senderInfo = {
      sender: this.currentUserId,
      username: // I would like to include username as an object.
      timestamp: Date.now(),
      message: 'wants to be friend with you.'
    }
    return new Promise((resolve, reject) => {
      this.afDB.list(`friend-requests/${recipient}`).push(senderInfo).then(() => {
        resolve({'status': true, 'message': 'Friend request has sent.'});
      }, error => reject({'status': false, 'message': error}));
    });
  }

#3

You would want to have on your component.ts

import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';

interface User {
  username: string,
  //etc
 }

export class SendMessagePage {
user: User;
observedUser$: Observable<User>;
userSubscription: Subscription;
 constructor() {
      observedUser$ = getCurrentUser();
  }

ionViewDidLoad(){
   userSubscription = observedUser$.subscribe(data => {
    user = data;
   })
  }

ionViewWillLeave(){
  userSubscription.unsubscribe();
  }

  getCurrentUser() {
    return this.afDB.object(`users/${this.currentUserId}`).valueChanges();
  }

   sendFriendRequest(recipient: string){
     let senderInfo = {
      sender: this.currentUserId,
      username: user.username
      timestamp: Date.now(),
      message: 'wants to be friend with you.'
    }
  }
}

Get the User, not just the username. Store it in user on ionViewDidLoad, then unsubscribe when the view will leave (That’s what I would do at least).

Of course, you’ll have to modify stuff a little bit since you’ll be getting getCurrentUser() from your provider, but the basic idea is the same

observedUser$ = this.yourProvider.getCurrentUser();

#4

Glad to see you again @jaydz and thank you :slight_smile:
It did help me, so it’s a bad idea to subscribe from the service?


#5

Thanks @JeffMinsungKim, good to see you too.

A bad idea? I don’t think it’s a bad idea. A more complicated idea, yes. You could subscribe in your provider, and publish data to your pages with Ionic Events (in the event that data changes).

But yes, you can subscribe in your provider too, then just return the user or user name to the page you need it in. I personally tend not to, but only because it adds a layer of complicated to the process that I simply haven’t needed for the most part.

I just took another look at your question and realized that subscribing FROM the provider was you main concern. Sorry!

As mentioned above, yeah, you totally can. You would just have to add a function to your provider to unsubscribe from observedUser$ and call it on ionViewWillLeave()


#6

@jaydz I’m not quite sure what you’ve just said, but it is more complicated. I get it.

Btw not really sure why I can’t add the subscription to this code. It all works fine on other pages.

private subscription: Subscription;

ionViewDidLoad(){
   let sub = observedUser$.subscribe(data => {
    user = data;
   })
   this.subscription.add(sub);
  } 

#7
this.subscription = observedUser$.subscribe(data => {
user = data
})
ionViewWillLeave(){
this.subscription.unsubscribe()
}

Sorry, forgot to add

this 

In my first post

So it would be

this.userSubscription = observedUser$.subscribe(data

#8

Oh, I know what breaks my code.
I’m actually subscribing multiple things so that’s why I tried to use add() method. Anyways thank you, everything works fine now :slight_smile:


#9

You can do this.

userSubscription: Subscription;
subscriptionArray: Subscription[];
this.userSubscription = observedUser$.subscribe(data = {
 user = data;
 })
this.subscriptionArray = [userSubscription, //other subscription]

On viewWillLeave

ionViewWillLeave(){
this.subscriptionArray.filter(sub => sub !== undefined).map(subs => subs.unsubscribe())
 }

I filter the subscription array for subscriptions that were not initialized based on code. But mapping the array of subscriptions to unsubscribe is probably what you’re looking for. At least, it’s a method that will work.

Using this.subscriptionArray.add(this.userSubscription) might work too, I just have never tried that syntax is all
(though I’m not sure .add is meant for that purpose)


#10

Yeap I’ve done it like that :smile:
I’m sorry but one more thing @jaydz .
I’m currently unsubscribing from ngOnDestroy()
It seems like much more safer than using ionic lifecycle hook to me. What do you think about that?
Should I stick with the ionic page leave method?

ngOnDestroy() {
    if (this.subscription !== undefined) {
      this.subscription.unsubscribe();
    }
  }

#11

Yeah, I would stick with the lifecycle hook


#12

Great! I better go fix my code.
Let’s keep in touch @jaydz Thank you for your time!


#13

No problem at all. Have fun!