Как обновить Angular HTTP-вызов при использовании таймера? - PullRequest
0 голосов
/ 10 мая 2018

Я создал наблюдаемый таймер для вызова HTTP-вызова, подобного этому,

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();

Это работает для вызова моего API каждые 30 секунд, однако после внесения изменений в данные я хотел бы немедленно обновить данные и не ждать, пока истечет таймер, но я не знаю, как это сделать. .

Кто-нибудь знает как? Я пытался отписаться и повторно подписаться, но это не сработало. Есть ли лучший способ сделать это?

Кроме того, нужны ли оба .share ()?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Перезагрузка каждые 30 секунд, вероятно, не очень хорошая идея, и вам лучше использовать websocket для этого варианта использования, но чтобы ответить на ваш вопрос, вы можете сделать что-то вроде этого:

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();
  }
}

И всякий раз, когда вы хотите принудительно перезагрузить данные, просто введите ваш сервис (A здесь) и выполните:

myAServiceInstance.reloadData();
0 голосов
/ 18 августа 2018

Я использовал альтернативный подход к этой проблеме.

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$;
}

Хотя я не эксперт в rxjs, вот как я думаю, что это работает:

При первой подписке значение null будет отправлено немедленно. Таймер будет подписан и будет выдавать значения каждые 30 секунд, что вызовет HTTP-запрос.

Это будет продолжаться до тех пор, пока не будет вызвано обновление, после чего будет выдано новое значение (неопределенное). Причина, по которой таймер находится в switchMap, заключается в том, чтобы гарантировать, что таймер отменяется (отменяется подписка) каждый раз, когда генерируется наблюдаемое обновление. Таймер будет переподписываться каждый раз, когда это происходит.

Наконец, shareReplay обеспечивает всех подписчиков одинаковой копией данных.

У меня не было особой причины использовать switchMap при выполнении запроса, за исключением того факта, что это самый безопасный оператор отображения в rxjs (или, как говорят в документации).

Надеюсь, это полезно.

0 голосов
/ 10 мая 2018

Попробуйте использовать interval отдельно и запускать observable каждые 30 с

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

}, 30000);   

httpRequest(){
    ..Observable..subscribe(res =>{
        this.variableToUpdate = res;
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...