Angular 8 .next doesn't seem to work as expected

r3plica

I am trying to create a service that authenticates a user and stores the token in the localStorage. I want other services (specifically the auth guard) to be able to access the current user, so I have set up the constructor of the authentication service like this:

currentUserSubject: BehaviorSubject<Token>;

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}

When a user logs in using a http POST request, if it's successful call the next method on the currentSubject like this:

return this.http.post<Token>(`${environment.identityServerUrl}/connect/token`, params, httpOptions)
    .pipe(map(user => {
        localStorage.setItem('currentUser', JSON.stringify(user));
        console.log(user);
        this.currentUserSubject.next(user);
    }));

The problem is, it doesn't seem to work. If I check my auth guard, it just sees the user as null. Only when I refresh is it populated (because of the authentication service constructor).

My auth guard looks like this:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { mapTo, take, filter } from 'rxjs/operators';

import { AuthenticationService } from './authentication.service';

@Injectable({ providedIn: 'root' })
export class AuthGuardService implements CanActivate {
    constructor(
        private router: Router,
        private authenticationService: AuthenticationService
    ) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
        return this.authenticationService.currentUserSubject.pipe(
            filter(user => !!user), 
            mapTo(true),
            take(1)
        );
    }
}

Does anyone know what I am doing wrong?


If I change my canActivate method to this:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean|UrlTree {
    var user = this.authenticationService.currentUserSubject.value;
    console.log(user);

    if (user) return true;

    this.router.navigate(["login"],{ queryParams: { retUrl: route.url} });
    return false;
}

It should work, but it just the console log shows null and so it just stays on the login page.

I saw that you can get .value from this article: https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

nash11

The subject next() method is used to send messages to an observable which are then sent to your angular components that are subscribed to that observable.

You have only created a subject but you have not created an observable that your guard can subscribe to.

currentUserSubject: BehaviorSubject<Token>;
currentUser$ = this.currentUserSubject.asObservable();

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}

By convention, observables have a $ sign at the end. Now that we have a created an observable which receives your subject's messages, we can subscribe to it in the guard.

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.authenticationService.currentUser$.subscribe(user => {
        console.log(user);
    });
}

I'm also not sure why you are using the filter, using map should be sufficient.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Completed property in Angular Material Stepper doesn't seem to work as expected

useState() - doesn't seem to work as expected

Script defer doesn't seem to work as expected

setLocation on a JButton doesn't seem to work as expected

Mockito thenAnswer doesn't seem to work as expected

Angular Controller doesn't seem to work

Angular Autocomplete doesn't seem to work right

Rails SQL select, doesn't seem to work as expected with the CASE statement

java.util.Date equals() doesn't seem to work as expected

golang TCPConn.SetWriteDeadline doesn't seem to work as expected

AMQP.Net Credit doesn't seem to work as expected

Object_hook in json module doesn't seem to work as expected

The date functions in snowflake doesn't seem to work as expected

Laravel 8 upsert doesn't work as expected

Regex doesn't work as expected in Angular Template

.gitignore Doesn't Seem To Work

SharedPreferences doesn't seem to work

Sorting doesn't seem to work

subquery doesn't seem to work

LIKE doesn't seem to work

:not() doesn't work as expected

totalSizeCap in logback doesn't seem to be working as expected

Java 8 Streams - Iterator doesn't work like expected

Jekyll "where" filter with site.data doesn't seem to work as expected

pysftp.connection.cd() doesn't seem to work as expected - any ideas why

I'm trying to create a a small box with a gradient background next to my header but it doesn't seem to work

Why timezone in angular doesn't work as expected in the following case

Angular4 FullName field validator doesn't work as expected

Angular reactive forms: valueChanges doesn't work as expected