RxJS shareReplay()不发出更新值

时间:2020-07-16 12:32:38

标签: angular typescript rxjs rxjs6 rxjs-observables

我有一个用户服务,该服务允许登录,注销并维护有关当前登录用户的数据:

ERROR 1049 (42000): Unknown database ' \. schema_belgarath_test_create.sql'

我使用user$ = this.http.get<User>('/api/user') .pipe( shareReplay(1), ); 是因为我不想多次调用该Web服务。

为简单起见,在其中一个组件上,我有这个功能,但是如果用户登录,我还有其他几件事要做:

shareReplay(1)
<div *ngIf="isUserLoggedIn$ | async">Logout</div>

但是,isUserLoggedIn$ = this.userService.user$ .pipe( map(user => user != null), catchError(error => of(false)), ); 在用户登录或注销后不会更改。刷新页面时确实会更改。

这是我的注销代码:

isLoggedIn$

我知道,如果将变量分配为null,则内部可观察对象不会重置。

因此,对于注销,我从以下答案中得到了提示:https://stackoverflow.com/a/56031703关于刷新logout() { console.log('logging out'); this.cookieService.deleteAll('/'); this.user$ = null; console.log('redirecting'); this.router.navigateByUrl('/login'); } 。但是,模板中使用的user $会使我的应用程序在尝试注销时立即陷入困境。

在我的尝试之一中,我尝试了shareReplay()

BehaviorSubject

除了刷新页面外,此方法效果更好。 auth-guard(user$ = new BehaviorSubject<User>(null); constructor() { this.http.get<User>('/api/user') .pipe(take(1), map((user) => this.user$.next(user)) .subscribe(); } logout() { ... this.user$.next(null); ... } )始终将用户$作为null并重定向到登录页面。

当我刚开始的时候,这似乎是一件容易的事,但是每次更改我都会陷入一个更深的洞。有解决办法吗?

1 个答案:

答案 0 :(得分:2)

对于这种情况,我将数据流(用户)与操作流(用户登录)结合使用,并使用combineLatest合并两者:

  private isUserLoggedInSubject = new BehaviorSubject<boolean>(false);
  isUserLoggedIn$ = this.isUserLoggedInSubject.asObservable();

  userData$ = this.http.get<User>(this.userUrl).pipe(
    shareReplay(1),
    catchError(err => throwError("Error occurred"))
  );

  user$ = combineLatest([this.userData$, this.isUserLoggedIn$]).pipe(
    map(([user, isLoggedIn]) => {
      if (isLoggedIn) {
        console.log('logged in user', JSON.stringify(user));
        return user;
      } else {
        console.log('user logged out');
        return null;
      }
    })
  );

  constructor(private http: HttpClient) {}

  login(): void {
    this.isUserLoggedInSubject.next(true);
  }

  logout(): void {
    this.isUserLoggedInSubject.next(false);
  }

我这里有一个有效的堆叠闪电战:https://stackblitz.com/edit/angular-user-logout-deborahk

user$是用户数据流和发出布尔值的isUserLoggedIn$流的组合。这样,我们可以使用映射并将返回的值映射到用户,如果用户已注销,则将其映射为null。

希望类似的东西对您有用。