koral
koral

Reputation: 2945

Angular2 RxJS reply corrent http requests periodically (polling)

I use Angular2 2.4.8. I fetch data using Http service:

fetchData(urls: string[], computer: Computer): Observable<Computer> {
    let stream$ = <Subject<Computer>>new Subject();
    let requests = new Map<string, Observable<Response>>();
    urls.forEach(url => {
        requests.set(url, this.http.get(url));
    });
    Observable.forkJoin(Array.from(requests, x => x[1]))
        .subscribe((responses: Response[]) => {
            // put data from responses into computer (API gives data in pieces)
            stream$.next(computer);
            stream$.complete();
        },
        (e: Response) => {
            // do something with error
            stream$.error(e.json());
        });
    return stream$.asObservable();
}

Now I need to refresh data periodically (polling). The difficulty is that the frequency should be different for different urls. Can I achieve this using Rx?

Maybe instead of parameter urls: string[] I could pass array of objects with url and fefresh frequuency. But I don't know how to solve this in Rx.

Upvotes: 0

Views: 430

Answers (2)

martin
martin

Reputation: 96891

This really depends on what exactly you're trying to do and how you want to handle the Observable returned from fetchData().

In general, if you want to periodically repeat a request you can use the repeatWhen() operator and chain it with delay():

urls.forEach(url => {
    requests.set(url, this.http.get(url)
      .repeatWhen(notifier => notifier.delay(XXX)));
});

Also, if you want to repeat the requests you can't use the forkJoin() because it'll just emit values and complete immediately.

In this case both combineLatest() or zip() seems good depending on what you want to achieve.

Upvotes: 0

Sebastian Sebald
Sebastian Sebald

Reputation: 16846

If you want to periodically make HTTP requests, you need to use .interval. This will allow you to "trigger" a new request now and then.

For example:

function poll (tuple) {
  return Rx.Observable.combineLatest(
    tuple.map(({url, time}) => {
      return Rx.Observable
        .interval(time)
        .switchMap(val => Rx.Observable.of(`${url}: ${val}`));
    })
  );
}

poll([
  { url: 'foo', time: 500 },
  { url: 'bar', time: 100 }
]).subscribe(val => console.log(val));
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

Replace the Rx.Observable.of part with your http service.

Upvotes: 1

Related Questions