1

I want to obtain the user data of a logged in user from Google Firebase. For this i wrote two methods; one obtains the authState and the other one obtains UserInfo containing more detailed information.

These are the two methods implemented in a service which is called UserService:

constructor(private fireStore: AngularFirestore, private fireAuth: AngularFireAuth) {
}

public async getAuthorizedUser(): Promise<UserInfo> {
  console.log('Awaiting Promise');
  const user: firebase.User = await this.fireAuth.authState.toPromise();
  console.log('User', user);
  return this.getUserInfo(user.uid);
}

private async getUserInfo(uid: string): Promise<UserInfo> {
  return this.fireStore.collection('users', ref => ref.where('uid', '==', uid))
             .get()
             .pipe(
               map((item: firebase.firestore.QuerySnapshot) => new UserInfo(item.docs[0].data(), item.docs[0].id))).toPromise();
}

I am calling the getAuthorizedUser method from a button event handler implemented in a component. The html element of the button looks like this:

<button mat-button (click)="test()">test</button>

and the test() method is implemented as:

async test() {
  console.log('Starting Test');
  const testVariable = await this.userService.getAuthorizedUser();
  console.log('Test', testVariable);
}

Furthermore, the userService is the dependency injected UserService.

The console shows:

Starting Test
Awaiting Promise

It therefore seems to me that the async call is not returning at all because i would expect to see a logging

Test

or

User {...}

or both.

What's wrong?

Edit - and partial answer:

After some more google research if found on angularfirebase.com that the authState should be called as

const user: firebase.User = await this.fireAuth.authState.pipe(first()).toPromise();

However this confuses me because i used the code below before i decided to change to observables instead of plain variables. The code worked, however i see no sign of any array which is returned by authState

this.fireAuth.authState.subscribe((user: firebase.User) => {
  if (user) {
    this.getUserData(user.uid);
  }
});

What is happening and why is my solution working?

2
  • What happens if you do: const user = await this.fireAuth.authState.pipe(first()).toPromise();? Commented Apr 7, 2019 at 11:07
  • Interestingly that works as i also found out a few minutes ago. But why do i need to use pipe(first())? I updated the question feel free to answer that problem Commented Apr 7, 2019 at 11:10

1 Answer 1

1

toPromise() creates a promise that will be resolved when the stream completes.

So if this.fireAuth.authState never completes, but emits values you can use the first operator to create a stream that completes after the first emitted value. Thus the promise resolves.

The subscribe handler on the other hand is called for every value.

Sign up to request clarification or add additional context in comments.

Comments

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.