Jon Sud
Jon Sud

Reputation: 11641

How to use interval to refresh data in reactive programming way?

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

Answers (1)

Shlomi Levi
Shlomi Levi

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

Related Questions