Reputation: 11641
I want to do refresh of the data every 5 seconds using reactive programming writing.
So I defined variable to hold the items I get from the server:
items$ = new BehaviorSubject(null);
And create another variable to get the request from the server.
for that I using interval
for do it every 5 seconds:
interval(5 * 1000).pipe(
startWith(0),
and using exhaustMap
to prevent another requests until the current will be resolved.
After I call to the http I save it in items$
and switch to items$
because I subscribe in the html template. (I don't want to subscribe twice)
this.http.get(this.url).pipe(
tap((r) => {
console.log({ r });
this.items$.next(r);
}),
switchMap(() => this.items$)
The problem is I get the results from http
only once.
So how to make the interval
still emit values and keep the idea of the refresh and switch to the data?
The full code codesandbox.io
@Component({
selector: "app-root",
template: ` {{ reload | async | json }} `
})
export class AppComponent {
title = "CodeSandbox";
items$ = new BehaviorSubject(null);
reload = interval(5 * 1000).pipe(
startWith(0),
exhaustMap(() =>
this.http.get(this.url).pipe(
tap((r) => {
console.log({ r });
this.items$.next(r);
}),
switchMap(() => this.items$)
)
)
);
url = "https://randomfox.ca/floof/";
constructor(private http: HttpClient) {}
}
Upvotes: 3
Views: 282
Reputation: 3305
The exhaustMap
operator is waiting for the inner observable to finish.
Move switchMap
outside of exhaustMap
and by doing so when the http
finishes then it will switch to your items$
observable stream.
reload = interval(5 * 1000).pipe(
startWith(0),
exhaustMap(() =>
this.http.get(this.url).pipe(
tap((r) => {
console.log({ r });
this.items$.next(r);
})
)
}),
switchMap(() => this.items$)
);
Upvotes: 1