Как схлопнуть собтия в стриме RXJS по времени?

В Angular и RXJS есть несколько способов схлопнуть (скомбинировать) события в стриме RXJS по времени, чтобы уменьшить количество обработчиков событий и улучшить производительность приложения. Один из самых распространенных способов - использование операторов debounceTime и throttleTime.

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

Пример использования оператора debounceTime для схлапывания событий в стриме RXJS по времени:

import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

const button = document.getElementById('my-button');

const clickStream = fromEvent(button, 'click');

clickStream.pipe(debounceTime(300)).subscribe(() => {
  console.log('Button clicked, but only after 300ms of inactivity');
});

В этом примере, обработчик события клика на кнопке будет вызываться только после 300 миллисекунд бездействия после последнего клика. Если в течение 300 миллисекунд произошло еще одно событие клика, то предыдущее событие будет проигнорировано.

Оператор throttleTime позволяет вызывать обработчик события через определенные промежутки времени. Он принимает аргумент - минимальное время между вызовами обработчика в миллисекундах. Если в этот промежуток времени происходят другие события, то они будут проигнорированы до тех пор, пока не пройдет заданное время.

Пример использования оператора throttleTime для схлапывания событий в стриме RXJS по времени:

import { fromEvent } from 'rxjs';
import { throttleTime } from 'rxjs/operators';

const button = document.getElementById('my-button');

const clickStream = fromEvent(button, 'click');

clickStream.pipe(throttleTime(300)).subscribe(() => {
  console.log('Button clicked, but only once every 300ms');
});

В этом примере, обработчик события клика на кнопке будет вызываться не чаще, чем раз в 300 миллисекунд. Если произойдет несколько кликов в течение 300 миллисекунд, только первый клик будет обработан, остальные будут проигнорированы.

Если вам нужно после задержки отлавливать событие со слайдером, кнопки увеличения-уменьшения и (де)фокусным событием, скроллете поулчасовой или датовый комонент, могут вам подойти пайпы буферных операторов:

import { fromEvent, combineLatest } from 'rxjs';
import { throttleTime } from 'rxjs/operators';

const input = document.getElementById('my-input');
const button = document.getElementById('my-button');
const slider = document.getElementById('my-slider');

const inputStream = fromEvent(input, 'input');
const buttonStream = fromEvent(button, 'click');
const sliderStream = fromEvent(slider, 'input');

combineLatest(
  inputStream.pipe(throttleTime(300)),
  buttonStream,
  sliderStream.pipe(throttleTime(300))
).subscribe(([inputValue, buttonClick, sliderValue]) => {
  console.log('Input, button and slider events combined:', inputValue, buttonClick, sliderValue);
});

В этом примере, обработчик будет вызываться только после 300 миллисекунд бездействия после последнего события с любого из элементов.