订阅Angular中的执行顺序

时间:2019-02-16 21:26:13

标签: angular typescript

我正在尝试验证用户是否在加载页面后立即登录,但是代码的执行顺序使此操作极为困难。这是检查用户是否登录的代码:

ngOnInit() {
    this.authService.authState.subscribe((user) => {
      this.user = user;
      this.loggedIn = (this.user != null);
      this.getUserProfile(user);
      console.log(this.loggedIn);
    });
    console.log(this.loggedIn);
    if (this.loggedIn) {
      console.log("Don't Redirect")
    } else {
      console.log("Redirect");
    }
  }

运行此代码时,此代码块首先执行:

console.log(this.loggedIn);
    if (this.loggedIn) {
      console.log("Don't Redirect")
    } else {
      console.log("Redirect");
    }

然后,如果用户登录此块,将执行第二个:

this.authService.authState.subscribe((user) => {
      this.user = user;
      this.loggedIn = (this.user != null);
      this.getUserProfile(user);
      console.log(this.loggedIn);
    });

如果用户未登录,那么订阅中的代码根本不会执行,因此我无法确定如何在用户注销后如何将用户从页面重定向到登录名并保留他们他们在哪里,如果他们已经登录,则获取用户个人资料。也许我只是盯着它看了很久,现在我还是无法理解它,但是任何一种方式都可以帮助您吗?

1 个答案:

答案 0 :(得分:2)

更新:

由于我们发现您要防止用户未登录就访问路由,因此建议使用路由保护器。

如果您想让用户坚持页面刷新,还需要使用localStorage

因此,当您登录时,将用户设置为本地存储:

this.authService.authState.subscribe((user) => {
  this.user = user;
  localStorage.setItem('user', this.user)
});

要在需要时抓取user,请使用:

this.user = localStorage.getItem('user');

用户注销后,请使用clear()removeItem

localStorage.removeItem('user');

现在,您可以在需要时访问该用户。不过,在这种情况下,请使用路由防护器来保护您的路由。请按照docs

中的步骤进行操作

这就是您的后卫的样子:

export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
    let url: string = state.url;

    return this.checkLogin(url);
  }

  checkLogin(url: string): boolean {
    const user = localStorage.getItem('user');
    if (user) {
      return true;
    }
    // route where you want to route and return false
    this.router.navigate(['/login']);
    return false;
  }
}

现在,您甚至不需要在组件中进行检查,因此请删除此内容:

if (this.loggedIn) {
  console.log("Don't Redirect")
} else {
  console.log("Redirect");
}

...因为警卫现在已经做好了!

最后,您还可以研究状态管理,例如使用ngrx-store,有一个插件也可以将localStorage连接到此。


原始答案:

在阅读插件时,实际上只有在用户登录或注销时才会通知您,而在两者之间没有任何通知。我猜您可以利用自己的变量/行为主题。我喜欢BehaviorSubject;)

因此在服务中,这里称为MyService

private appUser = new BehaviorSubject(null);
public appUser$ = this.appUser.asObservable();

modifyStatus(appUser: any) {
  this.appUser.next(appUser);
}

然后,在您登录用户的位置,添加回调:

this.authService.authState.subscribe((user) => {
    this.user = user;
    this.myService.modifyStatus(user);
});

注销后,您再次致电this.myService.modifyStatus(null)

然后您可以在组件中订阅...

this.myService.appUser$.subscribe((user: any) => {
  if (user) {
    console.log("Don't Redirect")
  } else {
    console.log("Redirect");
  }
});