简体   繁体   中英

How do I refresh an Angular HTTP call when using a timer?

I created a timer observable to call an HTTP call like this,

this.timer = Observable
       .timer(0, 30000)
       .switchMap(() => this.getMyData())
       .share();

 getMyData(){
     return this.http.get(this.url, this.options )
        .map(this.extractDataFromAPI)
        .retry(3)
        .catch(this.handleError)
        .share();

This works for calling my api every 30 seconds, however after I make an edit to the data I would like to immediately refresh the data and not wait for the timer to expire, but I do not know the proper way to do this.

Does anyone know how? I tried to unsubscribe and re-subscribe but that did not seem to work. Is there a better way to do this?

Also, are both .share()s needed?

Reloading every 30s is probably not a great idea and you should rather use websocket for that use case but to answer your question, you could do something like that:

class A {
  private forceReload = new Subject<void>();

  private timer = Observable.timer(0, 30000)
    .combineLatest(this.forceReload)
    .switchMap(() => this.getMyData())
    .share();

  getMyData() {
    return this.http
      .get(this.url, this.options)
      .map(this.extractDataFromAPI)
      .retry(3)
      .catch(this.handleError)
      .share();
  }

  reloadData() {
    this.forceReload.next();
  }
}

And whenever you want to force the reload of the data, just inject your service ( A here) and do:

myAServiceInstance.reloadData();

Try by using an interval separately and trigger the observable every 30 s

setInterval (()=> {
    his.httpRequest();      

}, 30000);   

httpRequest(){
    ..Observable..subscribe(res =>{
        this.variableToUpdate = res;
    });
}

I used an alternative approach to this problem.

private refresh$ = new Subject<void>();

get items(): Observable<T[]> {
  return this.getItems();
}

refresh(): void {
  this.refresh$.next();
}

getItems(): void {
  const timer$ = timer(0, 30000);

  const items$ = this.refresh$.pipe(
    startWith(null),
    switchMap(_ => timer$),
    switchMap(_ => this.getItems()),
    shareReplay()
  );

  return items$;
}

Although I'm no expert in rxjs, here's how I think it works:

On first subscribe, a value of null will be emitted immediately. The timer will get subscribed to, and emit values every 30 seconds, which will trigger an http request.

This will continue, until refresh is invoked, at which point a new value (undefined) will be emitted. The reason the timer is in a switchMap is to ensure that the timer is cancelled (unsubscribed) each time the refresh observable emits. The timer will be resubscribed to each time this happens.

Finally, shareReplay is there to ensure that all subscribers receive the same copy of the data.

I didn't have a particular reason to use a switchMap when making the request, other than the fact that its the safest mapping operator in rxjs (or so says the docs).

Hopefully this is useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM