Angular - вызывать функцию каждые 30 секунд, но учитывать время, затраченное на запуск функции - PullRequest
2 голосов
/ 16 апреля 2020

У меня есть приложение Angular 7, и я использую Rx JS.

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

Пример: если запрос занимает 10 секунд, то я хочу вызвать его снова через 40 секунд (30 + 10), а не через 20 (30 - 10).

Я пытаюсь с:


fetchList() {

   this.service.fetchListFromHttp()
      .pipe(
        finalize(() =>
          setTimeout(() => {
            this.fetchList();
          }, 30000)
        )
      )
      .subscribe(
         result => this.list = result,
         err => this.logError(err)
      );
}

Я мог бы представить, что когда http запрашивает, через 30 секунд он вызовет еще один вызов fetchInfo, но в результате получаются странные интервалы. Например, функция вызывается каждые 10 секунд или 20 секунд, и такие странные интервалы. Я предполагаю, что интервал всегда будет больше 30 секунд.

Ответы [ 3 ]

1 голос
/ 16 апреля 2020

Улучшение ответа SVNTY, вы можете сделать это так:

fetchInfo() {
  const passAndWait = (data) => interval(30000).pipe(
    take(1),
    ignoreElements(), // this is needed to discard interval numbers
    startWith(data),
  )

  // get data from network pass it to subscriber and wait for specified time
  // repeat will start everything again when interval completes with take(1)
  this.service.fetchInfoFromHttp().pipe(
    concatMap((data) => passAndWait(data)),
    repeat(Infinity), 
  ).subscribe();
}
1 голос
/ 16 апреля 2020

Вы подключаетесь к своему бэкэнду? Если вы - тот, кто закодировал API для получения информационной формы, socket.io, вероятно, то, что вы ищете, чтобы выполнить sh.

Вы рассматривали возможность использования RxJS? он поставляется с Angular, я уверен, что вы могли бы сделать sh что-то, что извлекает, затем делает паузу

что-то похожее на это может работать

this.service.fetchInfoFromHttp().pipe(delay(30 * 60 * 10000), () => ...), repeat(Infinity))

Вот ссылка на документацию по Rx JS

Rx JS задержка

Rx JS повтор

Socket.io

РЕДАКТИРОВАТЬ: Как я могу сделать таймер, используя наблюдаемые в Angular 9

ИЗМЕНИТЬ СНОВА:

Спасибо за ваш комментарий @ goga-koreli , возможно, debounce будет работать

https://www.learnrxjs.io/learn-rxjs/operators/filtering/debounce

0 голосов
/ 16 апреля 2020

используйте наблюдаемый от rx js https://stackblitz.com/edit/angular-q714uq

import { interval, Subject, PartialObserver, Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

после того, как библиотеки импорта установили интервал на 30, затем начните после окончания sh вызовите службу, когда служба снова получит результат интервал старта

ispause = new Subject();
private time = 30;
timer: Observable<number>;
timerObserver: PartialObserver<number>;
ngOnInit(){
    this.timer = interval(1000)
      .pipe(
        takeUntil(this.ispause)
      );    
    this.timerObserver = {         
      next: (_: number) => {  
         if(this.time==0){
           this.ispause.next;
           this.callservice();   
         }
         this.time -= 1;        
      }
    };
    this.timer.subscribe(this.timerObserver);    
}

callservice(){
  //after u get data
  this.service.fetchListFromHttp()
      .pipe(
        finalize(() =>
          this.time=30;
          this.timer.subscribe(this.timerObserver);
        )
      )
      .subscribe(
         result => this.list = result,
         err => this.logError(err)
      );

 }
...