Reputation: 409
I am using shareReplay() to cache an http call so it isn't repeated. However, at some point, I need to refresh the API call. Following various suggestions in stackoverflow, I introduce a Subject, so something like this:
private _refreshResponse$ = new BehaviorSubject<void>(undefined);
public response$: Observable<any> = this._refreshResponse$.pipe(
switchMap(() => this.http.get<any>(this.apiUrl)),
map((o) => o.message),
shareReplay(1)
);
constructor(private http: HttpClient) {
this.response$.subscribe();
}
public onRefreshClick() {
this.refreshResponse();
}
public refreshResponse() {
this._refreshResponse$.next();
}
And calling onRefreshClick() does indeed call the API again.
I introduced a new method to do some more work. I want to make an http call first, which will then call refreshResponse()
, and then some work with the new value. Something like the following:
public onDoSomeWork() {
// just create an observable... imagine it is an http call or something
this.fakeHttpCall()
.pipe(
tap(() => this.refreshResponse()),
switchMap(() =>
this.response$.pipe(
take(1),
tap((o) => console.log(o))
)
)
)
.subscribe();
}
But, of course, refreshResponse() does not wait for the returned value, so the value I get from response$ immediately after it is the previous value, NOT the new value. How can I "wait" for the new value.
Here's a demo: https://stackblitz.com/edit/angular-y2dtlg . The "response" is displayed in the browser (just a url from some random API I found). If you open the console, and click the "Work" button, it will refresh the URL displayed, and also write a URL to the console.log. But the console.log value is the previous value, not the updated one.
Note: I don't want to do the "console.log" in the this.response$.subscribe(() => ...)
method.
Thanks in advance!
EDIT: One (awful!) solution is to add a delay:
public onDoSomeWork() {
// just create an observable... imagine it is an http call or something
this.fakeHttpCall()
.pipe(
tap(() => this.refreshResponse()),
delay(2000),
switchMap(() =>
this.response$.pipe(
take(1),
tap((o) => console.log(o))
)
)
)
.subscribe();
}
This is just to show what I expect/where the problem lies if it's not clear...
Upvotes: 1
Views: 54