使用shareReplay进行多次订阅?

时间:2018-03-15 16:59:36

标签: angular rxjs

我有以下方法:

isLoggedIn() : Observable<boolean>{
  return this.isLoginSubject.asObservable().shareReplay(1).do(x=>console.log('called'));
}

在几个组件中,我有以下代码:

isLoggedIn: Observable<boolean>;
this.isLoggedIn = this._authService.isLoggedIn();

<header id="toolbar" *ngIf="isLoggedIn | async as isLoggedIn">
    <app-toolbar></app-toolbar>
</header>

我注意到,当我登录时,'called'被打印4次到控制台。我以为shareReplay只会导致一次订阅?

服务:

export class AuthService {
  isLoginSubject = new BehaviorSubject<boolean>(this.tokenNotExpired());
  private sharedLogin$ = this.isLoginSubject
  .shareReplay(1)
  .do(x => console.log('called'));

  constructor(private _httpClient: HttpClient) { }

  authenticate(username, password) {

   const user = {username, password};
    const headers = new HttpHeaders();
    headers.set('Content-Type', 'application/json');
   return this._httpClient.post<any>(environment.api_url + '/auth', user, {headers: headers}).do(x=>{

     this.isLoginSubject.next(true);
   });

  }

组件(ts):

 ngOnInit() {
    this.isLoggedIn = this._authService.isLoggedIn();
   }

组件(HTML):

<div [class]="bodyClasses">
  <aside id="sidebar" [ngClass]="{ 'active' : mobileNav }" (click)="mobileNav = !mobileNav" *ngIf="isLoggedIn | async as isLoggedIn">
    <app-sidebar></app-sidebar>
  </aside>

  <main id="main" class="wrapper">
    <header id="toolbar" *ngIf="isLoggedIn | async as isLoggedIn">
      <app-toolbar></app-toolbar>
    </header>
    <div id="content">

      <router-outlet></router-outlet>
    </div>
  </main>
</div>

我删除...| async并在控制台中只注意到一个called,但是当我退出时,它不会触发更改。注销时应隐藏的组件仍然显示:我在注销时执行以下操作:

 logout() {

    this.isLoginSubject.next(false);


  }

1 个答案:

答案 0 :(得分:4)

问题在于您多次调用this._authService.isLoggedIn()方法多次创建链this.isLoginSubject.asObservable().shareReplay(1)...(对于此方法的每次调用,它都会创建一个新链),所以如果您看到{{ 1}}打印4次,因为你订阅了4个不同的链。

所以你可以把链放到一个对象属性中,然后从'called'方法返回它:

isLoggedIn()

或者您可以公开private sharedLogin$ = this.isLoginSubject .shareReplay(1) .do(x => console.log('called')); isLoggedIn(): Observable<boolean> { return this.sharedLogin; } 并直接订阅它。