Повторное использование Rx JS Наблюдаемый для повторения асинхронного вызова? - PullRequest
1 голос
/ 21 января 2020

Как Rx JS Observable может выдать новое значение, если базовый поток событий не излучает новое значение?

Учитывая Angular компонент, который использует асинхронный c 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 s HttpClient .

Ответы [ 2 ]

1 голос
/ 22 января 2020

Вы также можете использовать 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

1 голос
/ 21 января 2020

Я бы рекомендовал как можно больше использовать наблюдаемые и оставаться в «реактивном уме»:

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();
  }
}
...