Rx JS: сделать один запрос API от функции, которая могла быть вызвана несколько раз - PullRequest
0 голосов
/ 31 марта 2020

контроллер компонента:

private updateSplitScreenService = () => {
    this.splitScreenService.emitNewState(this.products);
    this.splitScreenService.emitNewState(this.stores);
};

splitScreenService:


// emitNewState is called multiple times in quick succession but
// we want to only fire one API request and return the observable back 
// to the component
public emitNewState = (items: Products[] | Stores[]): void => {
    // If we already have a debounce active but a new call to emit 
    // the state has come in, cancel the current one.
    if (this.debounceTimeout) {
        clearTimeout(this.debounceTimeout);
    }

    // Create a new timeout
    this.debounceTimeout = setTimeout(() => {
        this.http.post().subscribe();
    }, 500);
};

Как вы можете видеть выше, я вызываю из своего компонента сервисную функцию, которая имеет настраиваемую функцию "debounce", чтобы гарантировать что запрос API произойдет, только если указанная функция не будет вызвана снова в течение 500 мс после последнего вызова. Любой вызов в течение 500 мс отменяет ранее настроенную функцию debounce для создания запроса API и снова устанавливает функцию тайм-аута для ожидания и вызова запроса API. Это гарантирует, что API вызывается только один раз.

Но если я хочу вернуть наблюдаемый запрос API обратно в мой компонентный контроллер, я сталкиваюсь с вопросом, как вернуть его из пользовательского debounce / сама функция тайм-аута. Цель состоит в том, чтобы отменить вызов, чтобы абонент не только получил только 1 результат, но и предыдущие вызовы были отменены (или не сделаны вообще).

1 Ответ

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

Попробуйте воспользоваться debounceTime, встроенным в Rxjs

import { debounceTime, switchMap } from 'rxjs';
...
emitNewState$ = new Subject();
...

ngOnInit() {
  this.listenToEmitNewState$();
}
....
emitNewState() {
  this.emitNewState$.next();
}

listenToEmitNewState$() {
  this.emitNewState$.pipe(
    debounceTime(500),
  ).subscribe(() => {
    // do what you want, but if you're going to do an HTTP call, use switchMap like how it is commented below
  });

  //this.emitNewState$.pipe(
    // debounceTime(500),
     //switchMap(() => this.http.post()),
  // ).subscribe(() => {....});
}

...