问题
I use shareReplay
to call only once (like a cache) a webservice to retrieve some informations :
In my service :
getProfile(): Observable<Customer> {
return this.callWS().pipe(shareReplay(1));
}
In multiple components :
this.myService.getProfile().subscribe(customer => {
console.log('customer informations has been retrieved from WS :', customer);
});
Now I want to add a method to force refresh the informations (bypass shareReplay only once). I tried with storing my observable in a variable, and set it to null before re-initialize it, but it seems to break components subscriptions..
Any help ?
Thanks
回答1:
I know this thread is old, but I think I know what the other answer meant about prepend a "reset" subject to push new values. Check this example:
private _refreshProfile$ = new BehaviorSubject<void>(undefined);
public profile$: Observable<Customer> = _refreshProfile$
.pipe(
switchMapTo(this.callWS()),
shareReplay(1),
);
public refreshProfile() {
this._refreshProfile$.next();
}
In the above snippet, all profile$
new subscribers will receive the latest emitted value (upon calling callWS()
once). If you wish to "refresh" the Customer being shared, you would call "refreshProfile()". This would emit a new value going through switchMapTo
, reassigning the replay value and also notifying to any profile$
open subscriber.
Have a nice one
回答2:
The other answers are all fine, but rather than having to reset the actual shareReplayed observable, a simpler approach might just be caching the result like so:
protected profile$: Observable<Customer>;
getProfile$(): Observable<Customer> {
if (!this.profile$) {
this.profile$ = this.callWS().pipe(shareReplay(1));
}
return this.profile$;
}
resetProfile() {
this.profile$ = null;
}
ref: https://blog.angularindepth.com/fastest-way-to-cache-for-lazy-developers-angular-with-rxjs-444a198ed6a6
回答3:
Sounds like you can prepend a Subject that will inject the new value with merge
:
private refresh$ = new Subject();
refreshProfile(...): void {
this.refresh$.next(/* whatever */);
}
getProfile(): Observable<Customer> {
return this.callWS().pipe(
merge(this.refresh$),
shareReplay(1),
);
}
回答4:
Thanks to the answer of martin (which didn't work for me) I found a way to do it :
protected profile: Observable<Customer>;
private refresh$ = new Subject<Customer>();
constructor() {
this.profile = this.refresh$.pipe(shareReplay(1));
this.resetProfile();
}
getProfile(): Observable<Customer> {
return this.profile;
}
resetProfile() {
this.callWS().subscribe(user => {
this.refresh$.next(user);
});
}
I think there is maybe something better/cleaner to do (using a Behavior Subject ?), so if you know something better ..
来源:https://stackoverflow.com/questions/54348406/rxjs-sharereplay-how-to-reset-its-value