无法取消订阅可在应用程序组件中观察到的

时间:2019-08-23 06:52:01

标签: angular rxjs

我创建了一个身份验证服务,用于检查本地存储中访问令牌的存在。为此,我创建了一个称为hasValidAccessToken的可观察对象。该函数发出boolean值。

我在app-component中观察到该订阅。问题是我无法取消订阅app-component中的订阅,因为它从未被销毁。

authentication.service.ts

 public isAuthenticatedSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(this.hasValidAccessToken());
    public isAuthenticated$: Observable<boolean>;

 isTokenExpired(): boolean {
        const expiresAt = localStorage.getItem("expires_at");
        const now = new Date();
        if (
            expiresAt &&
            parseInt(expiresAt, 10) < Math.floor(now.getTime() / 1000)
        ) {
            return false;
        }
        return true;
    }

    hasValidAccessToken(): boolean {
        if (this.hasAccessToken()) {
            return this.isTokenExpired();
        }
        return false;
    }

    hasAccessToken(): boolean {
        return !!localStorage.getItem("access_token");
    }

    decodeToken(token: string) {
        if (token) {
            return jwt_decode(token);
        }
    }

app.component.ts

this.isAuthenticatedSubscription = this.oauthService.isAuthenticated$.subscribe(
                data => {
                    if (data) {
                        this.router.navigate(["home"]);
                    } else {
                        this.router.navigate(["login"], {
                            state: { data: "session has been expired" }
                        });
                    }
                }
            );

2 个答案:

答案 0 :(得分:3)

您可以使用take在设置一定数量的发射量之后使您的Observable完整。

this.isAuthenticatedSubscription = this.oauthService.isAuthenticated$
    .pipe(
        take(1)
    )
    .subscribe(
        data => {
            if (data) {
                this.router.navigate(["home"]);
            } else {
                this.router.navigate(["login"], {
                    state: { data: "session has been expired" }
                });
            }
        }
    );

编辑:尽管这可以解决您的问题,但@Dino是正确的,您不应该取消订阅该可观察的内容,因为您的应用程序的登录状态取决于此。您应该将此逻辑移至AuthGuard。

答案 1 :(得分:3)

您永远不应取消订阅该可观察的项目。您基本上是在重新创建Authentication Guard。想象一下,如果您确实取消订阅它,并且在应用程序中的某一时刻,您丢失了身份验证令牌(注销,否则它将过期...)。由于您已取消订阅该应用程序,因此该代码将永远不会触发:

 else {
         this.router.navigate(["login"], {
             state: { data: "session has been expired" }
         });
      }

我的建议是通过创建前面提到的Authentication Guard来替换逻辑。这样,您将可以使用canActivate保护路线,这也是最佳做法。