I have looked at a number of resources including this, this and this, but I have not been able to achieve the desired result.
All I'm trying to do is authenticate a user (using firebase) and then once authenticated, load up their profile and store it in a variable userProfile
before loading up the next page Dashboard:
My Signin service:
public signinUser(user: User) {
this.af.auth.login({
email: user.email,
password: user.password
},
{
provider: AuthProviders.Password,
method: AuthMethods.Password
}
)
.then(
success => {
console.log('Authenticated');
this.getProfile().subscribe( // PROBLEM is here
profile => {
console.log(profile);
console.log('Profile Loaded');
this.router.navigate(['/dashboard']);
}
)
}
)
.catch(function (error) {
...
console.log('ERROR SIGNING USER IN');
}
My getProfile()
method:
public getProfile(): Observable<any> {
return this.af.database.object('/profiles/' + this.user.uid)
.flatMap(
profile => {
console.log('inside success');
console.log(profile);
this.userProfile = <User>profile;
console.log('getProfile has completed');
return profile;
},
error => {
console.log(error)
});
This is how part of the log looks:
Authenticated
auth.service.ts:104 ERROR SIGNING USER IN
auth.service.ts:105 TypeError: Cannot read property 'subscribe' of undefined
at auth.service.ts:91
at ZoneDelegate.invoke (zone.js:232)
at Object.onInvoke (ng_zone.js:238)
at ZoneDelegate.invoke (zone.js:231)
at Zone.run (zone.js:114)
at zone.js:502
at ZoneDelegate.invokeTask (zone.js:265)
at Object.onInvokeTask (ng_zone.js:229)
at ZoneDelegate.invokeTask (zone.js:264)
at Zone.runTask (zone.js:154)
auth.service.ts:106 Cannot read property 'subscribe' of undefined
auth.service.ts:184 inside success
auth.service.ts:185 Object {confirmPassword: "123123", email: "[email protected]", github: "aaa" name: "a", password: "123123"…}
auth.service.ts:188
getProfile has completed()
auth.service.ts:185
I can see that the methods, individually are working as intended. The user authenticates, and the profile is loaded (shown in log). The problem lies with the subscribe event for reasons which I do not know.
I think the problem is that getProfile
doesn't really return an Observable
.
You use flatMap
so you can chain the observable sequence and return the profile as an observable. But in order for this to work, your callback inside the flatMap
should return a promise or an observable (as I learned from this answer). Otherwise the chain of observables is broken.
So what you probably need to do is something like:
public getProfile(): Observable<any> {
return this.af.database.object('/profiles/' + this.user.uid)
.flatMap(
profile => {
console.log('inside success');
console.log(profile);
this.userProfile = <User>profile;
console.log('getProfile has completed');
return Promise.resolve(profile);//<-- this is what needs to be changed
},
error => {
console.log(error)
});
Ok this is strange but I restarted webpack and it seems to have cured the problem.
This is how the code looks and it is correctly authenticating via the promise, and then on success it loads the profile which then loads the next page:
My signinUser
method:
public signinUser(user: User) {
this.af.auth.login({
email: user.email,
password: user.password
},
{
provider: AuthProviders.Password,
method: AuthMethods.Password
}
)
.then(
success => {
console.log('Authenticated');
this.getProfile().subscribe(
profile => {
this.router.navigate(['/dashboard']);
},
error => console.log(error)
)
And my getProfile
method:
public getProfile(): Observable<User> {
return this.af.database.object('/profiles/' + this.user.uid)
.map(
profile => {
console.log('inside success');
console.log(profile);
this.userProfile = <User>profile;
console.log(this.userProfile);
return profile;
},
error => {
console.log(error)
});
}
The callstack:
- User is authenticated
- Subscribe to getProfile and wait for method to finish...
- GetProfile() method executes
- Profile is set
- Page is redirected
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With