Reputation: 667
I am creating a custom login service with AuthGuard
from Angular
. I have a SessionService
which have methods such a login()
or onUserLoggedIn()
which basically returns BehaviorSubject
with the current value of user status (logged in/not logged in). Based on this service I created an implementation of AuthGuard implements CanActivate
service. I call onUserLoggedIn
method and check the current value in subject. The problem here is that in login
method value is changed after the AuthGuard
call onUserLoggedIn
. Therefore in a first attempt I receive false value from BehaviorSubject but when I try the second time, I received a true value.
How can I change the implementation of those two services to achieve current value in a first attempt?
AuthGuard:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
: Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
console.log('auth');
return this.sessionService.onUserLoggedIn()
.pipe(
map(res => {
console.log('res', res);
return res;
}),
take(1),
tap(allowed => {
console.log(allowed);
if (!allowed) {
this.router.navigate(['/login']);
}
})
);
}
SessionService:
private isLoggedIn = new BehaviorSubject(false);
constructor(private apiService: ApiService) {
}
login(user: User): Observable<any> {
console.log('hello before');
return this.apiService.post(`${BASE_URL}/login`, user)
.pipe(
tap((token: Token) => {
this.isLoggedIn.next(true);
localStorage.setItem('token', token.token);
console.log('hello');
})
);
}
onUserLoggedIn() {
return this.isLoggedIn;
}
First attempt goes with printing value:
The second one (which I expect to be first):
Upvotes: 0
Views: 2032
Reputation: 353
The nature of BehaviorSubject is, it emit the given value immediately whenever you subscribe.
So based on your use case use Subject. Also use skip operator to skip the first value.
return this.sessionService.onUserLoggedIn()
.pipe(
take(1),
map(res => {
console.log('res', res);
return res;
}),
tap(allowed => {
console.log(allowed);
if (!allowed) {
this.router.navigate(['/login']);
}
})
);
}
use startsWith(false)
in other components.
Upvotes: 1
Reputation: 1027
Can you try returning it asObservable?
onUserLoggedIn() {
return this.isLoggedIn.asObservable();
}
Upvotes: 0