0

I am very confused as to why the variables is not holding.
I have a variable user which is assigned with the data in userData(). But it's undefined when console log within the constructor and ProfilePage.

enter image description here

share-service.ts

export class ShareService {
  uid: string;
  user;

  constructor(public db: AngularFireDatabase) {
    let currentUser = firebase.auth().currentUser;
    this.uid = currentUser.uid;
    this.userData();
    console.log('[constructor]user: ', this.user);
  }

  userData() {
    this.db.object(`users/${this.uid}`).snapshotChanges().subscribe(data => {
      this.user = data.payload.val();
      console.log('[userData]user: ', this.user);
    });
  }

  getUser() {
    return this.user;
  }

}

profile.ts

export class ProfilePage {
  user;

  constructor(public navCtrl: NavController, public firebaseService: FirebaseService, shareService: ShareService) {
    console.log('[profile.ts]', shareService.getUser());
  }

}
  • "angularfire2": "5.0.0-rc.4",
  • "firebase": "4.8.2",
  • "ionic-angular": "3.9.2",
  • "rxjs": "^5.5.6",
  • "@ionic/app-scripts": "3.1.8",
  • "typescript": "2.4.2"

I have already tried searching for similar questions like for example this and read that it has something to do with how angular is asynchronous and then upon further investigation I read that promise is needed like this. I also read somewhere that .then() should be used.

I tried several ways to implement those into this use case scenario but all turned out with syntax errors.

In need of advice, please.

5
  • I dont know what you want to do, but you have an observable there, not a promise. What is your question? Commented Feb 9, 2018 at 4:31
  • @AlanGrosz I have a variable user which is assigned with the data in userData(). But it's undefined when console log within the constructor Commented Feb 9, 2018 at 4:38
  • where exactly you want to access this.user? in the constructor? Commented Feb 9, 2018 at 4:44
  • @SurajRao accessing on other page by importing import {ShareService } from '../../providers/share-service/share-service' and then getting by calling shareService.getUser(); Commented Feb 9, 2018 at 5:07
  • check my answer.. call getUser().then(data=> //in here) Commented Feb 9, 2018 at 5:07

2 Answers 2

2

Angular provides Async Pipe for this type of Async methods.

user information will be come from firebase server, and it will take time.
in the meanwhile, javascript continues its execution.

that's why you got this.user as undefined, because when JS execute that line, data is not come from server and not assign to it.

so we need to handle this type of methods either by

so try this

share-service.ts

export class ShareService {
 uid: string;

 constructor(public db: AngularFireDatabase) {
 let currentUser = firebase.auth().currentUser;
 this.uid = currentUser.uid;
 }

 getUser() {
   return this.db.object(`users/${this.uid}`)
     .snapshotChanges()
     .map(data => data.payload.val());
 }
}

profile.ts

export class ProfilePage {
 user;

 constructor(public navCtrl: NavController, public firebaseService: 
  FirebaseService, shareService: ShareService) {
  this.user = shareService.getUser();
 }
}

In Template

<div *ngIf="user | async as _user; else loadingUsers">
  {{_user.username}}
</div>
<ng-template #loadingUsers>
  Loading...
</ng-template>
Sign up to request clarification or add additional context in comments.

3 Comments

It's simple and it works. But what if I need to use this.user.some_property to do some logic inside code?
for example, in template <div (click)="editUser(user)">edit</div> or this.user = shareService.getUser().map(user => this.data = user);
this blog post will be helpful
1

Here is how you read it..

 userData() {
    return this.db.object(`users/${this.uid}`).snapshotChanges()
    .pipe(map(data => {

      this.user = data.payload.val();
      return this.user;
      console.log('[userData]user: ', this.user);
    }));//import { map } from 'rxjs/operators/map';

}

If you want to access it anywhere use subscribe() on getUser().

  getUser(){
    if(!this.user){
        return this.userData();//return the db call if not set
    }else{
    return of(this.user);//import {of} from 'rxjs/Observable/of;'
  }

In constructor,

  constructor(public db: AngularFireDatabase) {
    let currentUser = firebase.auth().currentUser;
    this.uid = currentUser.uid;
    this.getUser().subscribe(u=>{
        console.log('[constructor]user: ', u);
    });//subscribe to the observable.
  }

21 Comments

It's not working, console.log not even getting called. How do i do it with async/await instead?
what do you mean not getting called? any console errors?
no error at all.. console.log inside .then is not executed.
sorry. my bad.. it is return Promise.resolve(this.user);
Still the same.. userData() { return this.db.object(users/${this.uid}).snapshotChanges().toPromise().then(data => this.user = data.payload.val(); console.log('[userData]user: ', data.payload.val()); return this.user; })} console.log inside userData() i also not being executed.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.