应用状态未在单独的浏览器标签中更新

时间:2019-08-20 14:07:39

标签: angular

在我的Angular应用中,我已经实现了电子邮件确认,因此,在创建新用户帐户时,确认电子邮件将发送到注册的电子邮件地址。

用户可以未经确认的身份登录,但是他们只能访问应用程序的有限功能,直到他们访问确认电子邮件中的链接(确认链接会在单独的选项卡中打开应用程序)。

我的AuthService的相关部分如下所示:

private readonly KEY_AUTH = '_auth';

private currentAuthSubject = new BehaviorSubject<Auth>(
  JSON.parse(localStorage.getItem(this.KEY_AUTH)));

// My Components subscribe to this Observable to get notified on Auth changes
public currentAuth = this.currentAuthSubject.asObservable();

// This function is used to set the authentication object on login
// (or delete it on logout by calling setAuth(null))
setAuth(auth: Auth) {
  if (auth) {
    localStorage.setItem(this.KEY_AUTH, JSON.stringify(auth));
  } else { localStorage.removeItem(this.KEY_AUTH); }
  this.currentAuthSubject.next(auth);
}

// This function is called when the user is already logged in and being confirmed
// (by clicking the confirmation link)
setAuthConfirmed() {
  const auth = this.currentAuthSubject.value;
  if (auth) {
    auth.confirmed = true;
    localStorage.setItem(this.KEY_AUTH, JSON.stringify(auth));
    this.currentAuthSubject.next(auth);
  }
}

确认基本上可以正常工作,但是我遇到以下有问题的情况:

  1. 在选项卡 A 中,未经确认的用户已登录到应用程序(功能受限)。
  2. 在选项卡 B 中,他们打开电子邮件,然后单击确认链接。
  3. 该应用程序将在选项卡 C 中打开,发生确认,并且用户具有全部功能。

问题来了:

  1. 在选项卡 A 中,即使在预订了currentAuth的组件之间导航,用户仍具有受限的功能。

    在此标签中,confirmed对象的Auth字段仍为false

    只能通过刷新页面来解决此问题。

是否可以在选项卡 A 中更新身份验证状态,而不必手动刷新整个页面?

我真的很感谢任何建议。

5 个答案:

答案 0 :(得分:0)

您可以订阅localStorage更改:

window.addEventListener('storage', function(event){
    if (event.storageArea === localStorage) {
        // It's local storage
    }
}, false);

另一个认为您可以做的是做一个时间间隔,检查它在localStorage上是否已更改,如果是,则发出新值。

答案 1 :(得分:-1)

向服务器发出http请求,以每2秒检查一次电子邮件是否得到确认,例如,通过在服务器中创建新的rest服务以进行电子邮件确认检查,或者您可以使用websocket以便服务器可以通知浏览器有关确认的信息,它将被更新

答案 2 :(得分:-1)

您可以尝试创建一个拦截器,该拦截器将检查每个请求的currentAuth并在可能和需要时对其进行更新。

因此,在选项卡 A 中,它将在选项卡 C

中以更新后的第一个请求进行更新。

答案 3 :(得分:-1)

如果用户未通过身份验证,则可以使用localstorage设置某种标志。订阅本地存储事件更改Stackoverflow Question

与此相关的还有一篇很好的文章,关于标签Link

之间的共享会话

答案 4 :(得分:-1)

为什么不使用ngOnInit()和ngAfterViewInit()处理标签C的任务?

在ngOnInit中调用setAuthConfirmed()(在收到请求后立即运行,但在视图呈现之前运行),并在ngAfterViewInit()中检查用户身份验证。当我实现您要执行的操作时,将使用具有应用程序范围的全局用户类。因此,我可以使用布尔属性来控制登录的用户界面和未登录的用户界面以及权限。我在登录组件中设置了全局用户类的值。然后,此后访问的每个组件都会检查用户类属性,以决定如何与用户打交道。

生命周期挂钩可能会为您提供所需的东西: https://angular.io/guide/lifecycle-hooks