【问题标题】:Re-using an RxJS Observable to repeat an asynchronous call?重新使用 RxJS Observable 重复异步调用?
【发布时间】:2020-05-07 19:19:06
【问题描述】:

如果底层事件流不发出新值,RxJS Observable 如何发出新值?

给定一个 Angular 组件,它使用异步 pipe 来显示用户名;

export class MyComponent implements OnInit {

  public user$!: Observable<User>;

  constructor(private readonly ms: MyService)

  ngOnInit() {
    this.user$ = this.ms.getUser();
  }
}
<ng-container *ngIf="user$ | async as user; else empty">
  {{ user.name }}
</ng-container>

<ng-template #empty>
  No user here.
</ng-template>

...假设一段时间过去了,我想通过调用异步函数this.ms.getUser() 再次尝试获取用户,我该怎么做?

AFAIK,我不能简单地覆盖 Observable $captcha

export class MyComponent implements OnInit {

  public user$!: Observable<User>;

  constructor(private readonly ms: MyService)

  ngOnInit() {
    this.user$ = this.ms.getUser();
  }

  getUserAgain() {
    // Wrong. This would be a new/different Observable.
    // The UI would not update.
    this.user$ = this.ms.getUser();
  }
}

MyService 服务返回一个 Observable,因为它只是 Angular 的 HttpClient 的一个薄包装。

【问题讨论】:

标签: angular typescript rxjs ngrx


【解决方案1】:

你也可以使用repeatWhen:

export class MyComponent implements OnInit {

  public user$!: Observable<User>;
  private repeat$ = new Subject()

  constructor(private readonly ms: MyService) {}

  ngOnInit() {
    this.user$ = this.ms.getUser().pipe(
      repeatWhen(() => repeat$)
    );
  }

  getUserAgain() {
    this.repeat$.next();
  }
}

https://stackblitz.com/edit/eoznkm

【讨论】:

  • 我真的很喜欢这个答案!!!我习惯于按照之前答案中发布的方式这样做,并且总是忘记模式。使用repeatWhen() 更具描述性和直观性。它在管道中的读数也更好。这应该是公认的答案。
【解决方案2】:

我建议尽可能多地使用 observables 并保持“反应性思维”:

export class MyComponent {
  public refreshUser$: Subject<void> = new Subject();

  public user$!: Observable<User> = this.refreshUser$.pipe(
    startWith(undefined),
    switchMap(() => this.ms.getUser())
  );

  constructor(private readonly ms: MyService) {}

  public getUserAgain() {
    this.refreshUser$.next();
  }
}

【讨论】:

  • 谢谢。你能解释一下startsWith的必要性吗? AFACT,当组件被渲染并立即调用switchMap 时,异步管道将订阅。
  • 你是否使用startWith 来强制 Observable 在组件渲染时发出一个值?如果没有startWith,在调用getUserAgain 之前不会发出任何值?
  • 没错。这样可以节省您从 ngOnInit 调用 getUserAgain :)
猜你喜欢
  • 2019-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2017-05-24
  • 2017-04-18
  • 2020-03-05
相关资源
最近更新 更多