Reputation:
I am using angular and firestore. I'm checking firestore for a value inside my route guard.
I have found that on page refresh, it returns as undefined. However, if I just hardcode a return of true or false, it works.
Any logs within my if statement always return correctly, but doesn't seem to be updating my global variable for some reason.
If I use my site navigation to get back to the root and navigate through my site, it works correctly. However, when I refresh the page, it returns as undefined.
Could it be a scoping issue?
Route Guard
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Subscription } from 'rxjs/Subscription';
//testing
import { Observable } from 'rxjs/Observable';
import { AngularFireAuth } from 'angularfire2/auth';
@Injectable()
export class CheckBillingService implements CanActivate {
private _subscription: Subscription;
private userBillingDocRef: AngularFirestoreDocument<any>;
userBilling: Observable<any>;
public activeAccount:Observable<boolean>
constructor(private authService: AuthService,
private router: Router,
private auth: AngularFireAuth,
private readonly afs: AngularFirestore) {}
canActivate(): Observable<boolean> {
this.authService.user.subscribe((user) => {
if (user) {
var userId = user.uid;
this.userBillingDocRef = this.afs.doc('user_billing/${userId}');
this.userBilling = this.userBillingDocRef.snapshotChanges();
this.userBilling.subscribe((value) => {
const data = value.payload.data();
if (data.account_status == "Active") {
this.activeAccount = Observable.of(true);
console.log('inside if statement for active = ', this.activeAccount);
} else {
this.activeAccount = Observable.of(false);
console.log('inside if statement for not active = ', this.activeAccount);
this.router.navigate(['resubscribe']);
return Observable.of(false);
}
console.log('userBilling.subscribe = ', this.activeAccount);
});
console.log('just outside userBilling.subscribe = ', this.activeAccount);
}
});
// When refreshig my page, this returns as undefined.
// If I navigate to the correct page and work my way through the site it works fine
// However, refresh returns undefined.
console.log('out of auth = ', this.activeAccount);
return this.activeAccount;
}
}
Upvotes: 1
Views: 930
Reputation: 19754
Observables can be asynchronous; they're usually used for this purpose. Code outside of subscribe is in such cases executed before one inside subscribe.
That's why it seems like it's "not updating" variables. It is, but you're not accessing them at the correct time. It works when you hardcode the values because then subscribe is executed synchronously.
Upvotes: 1
Reputation: 2503
According to your code the page will run before your observable method is returned as it's running asynchronously, instead return the full method as observable like so
canActivate(): Observable<boolean> {
return Observable.create(observer=> {
this.authService.user.subscribe((user) => {
if (user) {
var userId = user.uid;
this.userBillingDocRef = this.afs.doc('user_billing/${userId}');
this.userBilling = this.userBillingDocRef.snapshotChanges();
this.userBilling.subscribe((value) => {
const data = value.payload.data();
if (data.account_status == "Active") {
this.activeAccount = Observable.of(true);
// observe here
observer.next(true)
console.log('inside if statement for active = ', this.activeAccount);
} else {
this.activeAccount = Observable.of(false);
// observe here
observer.next(false)
console.log('inside if statement for not active = ', this.activeAccount);
this.router.navigate(['resubscribe']);
}
console.log('userBilling.subscribe = ', this.activeAccount);
});
console.log('just outside userBilling.subscribe = ', this.activeAccount);
}
});
});
// When refreshig my page, this returns as undefined.
// If I navigate to the correct page and work my way through the site it works fine
// However, refresh returns undefined.
console.log('out of auth = ', this.activeAccount);
}
Observe where I wrapped everything in Observer.create
which you can learn more here https://stackoverflow.com/a/44334611/5836034
then observer.next
will return what you really want the canActivate
hook to react on
// observe here
observer.next(true)
observer.next(false)
Upvotes: 5