0

I have a component that calls "getUserDocInfo()" which is in its own service. How would I go about calling that function and then using the returned data for further code?

My Component

 getToken(){
    this.userService.getUserDocInfo();
    // once this is called I would like to use some of the values in the returned data
  }

My Service

getUserDocInfo() {
    this.getUserInfo().then(() => {
      this.userDoc = this.afs.doc(`users/${this.userID}`);
      this.user = this.userDoc.snapshotChanges();
      this.user.subscribe(value => {
        const data = value.payload.data();
      });
    })
  }

 async getUserInfo() {
    const user = await this.authService.isLoggedIn()
    if (user) {
      this.userID = user.uid;
    } else {
      // do something else
    }
  }

Any help on best practises here would be greatly appreciated.

Que
  • 957
  • 2
  • 14
  • 35
  • 1
    The keyword you're looking for is `return`. I strongly suggest you don't mix promises and observables. Learn observables, and stick to them. – JB Nizet Sep 20 '18 at 16:12
  • Thanks. My question is primarily stemmed around how to use that returned data. I only want a segment of it. Do I this.userService.getUserDocInfo().subscribe to something? – Que Sep 20 '18 at 16:15
  • Yes. But for that to work, getUserDocInfo() must **return** an observable. – JB Nizet Sep 20 '18 at 16:16
  • I allways say: "services return Observables -or Promise-, component subscribe to services". In general is a better aproach. Mainly because you can change the service and you needn't change the component. e.g. at first your service can read the data from a file, after read from dbs.. Therefore, you can combine severall observables in a component. If you want to make a "cache" of some tables, is the service who serve the "cacheable" table (or if not a call to a server). All this not force you to change component – Eliseo Sep 20 '18 at 16:17

1 Answers1

1

One way to do it is implementing an callback that you would pass on the method parameters. Something like this.

getUserDocInfo(callback) {
    this.getUserInfo().then(() => {
      this.userDoc = this.afs.doc(`users/${this.userID}`);
      this.user = this.userDoc.snapshotChanges();
      this.user.subscribe(callback);
    })
  }

getToken(){
    this.userService.getUserDocInfo((value) => {
        console.log(value.payload.data());
    });
  }

You could return an Observable too and subscribe to it on you component context and you could handle the subscriptions as you want.

import { Observable } from 'rxjs/Observable/';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';

@Injectable()
export class AlertService {

  //constructor and properties...

  getUserDocInfo(): Observable<any> {
    Observable.fromPromise(this.getUserInfo()).mergeMap(() => {
      this.userDoc = this.afs.doc(`users/${this.userID}`);
      this.user = this.userDoc.snapshotChanges();
      return this.user.map(user => user);
    });
  }
}

@Component(...)
export class MyComponent implements OnDestroy {

  subscriptions: Array<Subscription> = new Array;

  //constructor

  getToken(){
    const sub = this.userService.getUserDocInfo().subscribe((value) => {
        console.log(value.payload.data());
    });
    this.subscriptions.push(sub);
  }

  ngOnDestroy() {
    this.subscriptions.forEach(sub => sub.unsubscribe());
  }
}
ygorazevedo
  • 487
  • 1
  • 4
  • 14
  • Fantastic, the first option works! - Thank you for taking the time to give a detailed answer! - Are there any pro's or con's between the two of these? (I can accept the answer in a few mins ) – Que Sep 20 '18 at 16:21
  • I prefer the second one. Because you can control the subscription and close it when you don't need it anymore, in your case would be when the component is destroyed through `ngOnDestroy`, and I indeed recommend you to do so, because if you open a decent amount of subscriptions and don't close it you would have some problems of performance. Let me edit my answer to show you what I mean. – ygorazevedo Sep 20 '18 at 16:25
  • The second one is incorrect: you're returning a promise, not an observable. – JB Nizet Sep 20 '18 at 16:27
  • `snapshotChanges` returns an Observable wich is set to `this.user`, `then` returns `this.user` and the method returns `then` so I'm indeed returning an Observable or is something missing? – ygorazevedo Sep 20 '18 at 16:42
  • Indeed @JBNizet is right. Let me fix it real quick. – ygorazevedo Sep 20 '18 at 16:50