简体   繁体   English

Angular 8 .next似乎无法正常工作

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

I am trying to create a service that authenticates a user and stores the token in the localStorage. 我正在尝试创建对用户进行身份验证并将令牌存储在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: 我希望其他服务(特别是auth Guard)能够访问当前用户,因此我已经设置了身份验证服务的构造函数,如下所示:

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: 当用户使用http POST请求登录时,如果成功登录,请像下面这样在currentSubject上调用next方法:

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方法更改为此:

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. 它应该可以工作,但是只是控制台日志显示为null ,因此它停留在登录页面上。

I saw that you can get .value from this article: https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0 我看到您可以从本文中获取.valuehttps : //medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

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. 主题next()方法用于将消息发送到可观察对象,然后将消息发送到订阅该可观察对象的角度组件。

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. 我也不确定为什么要使用filter ,使用map应该足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM