Reputation: 10613
How can an RxJS Observable emit a new value, if the underlying event stream doesn't emit a new value?
Given an Angular component which uses an async pipe
to display a user's name;
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>
...imagine some time passes and I want to try getting the user again by calling the asynchronous function this.ms.getUser()
, how can I do this?
AFAIK, I cannot simply overwrite the 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();
}
}
The service MyService
returns an Observable because it's just a thin wrapper around Angular's HttpClient
.
Upvotes: 1
Views: 1073
Reputation: 14089
You could also use 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
Upvotes: 3
Reputation: 23793
I'd recommend to use observables as much as possible and stay in a "reactive mind":
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();
}
}
Upvotes: 1