Гарантия `n` секунд между излучением без ожидания изначально - PullRequest
0 голосов
/ 10 февраля 2019

Учитывая поток событий, например (каждый - равен 10ms)

--A-B--C-D

С debounceTime(20) мы получаем

-----------D

С throttleTime(20) мы получаем

--A----C--

С throttleTime(20, undefined, {leading: true, trailing: true} мы получаем

--A----CD

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

--A-----C--D

В общем случае throttleTime с trailing: true ближе всего, но иногда это может привести к тому, что выход trailing окажется слишком близко к выводу leading.

Пример кода можно найти на rxviz.com

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

1.Создайте задержку

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

const { EMTPY, of, concat } = Rx;
const { concatMap, delay } = RxOperators;

event$.pipe(
  concatMap(item => concat(of(item), EMPTY.pipe(delay(20))))
);

enter image description here

2.ConcatMap к таймеру

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

const { timer } = Rx;
const { concatMap, ignoreElements, startWith } = RxOperators;

event$.pipe(
  concatMap(item => timer(20).pipe(ignoreElements(), startWith(item)))
);

3.Индекс с интервалом (не оптимально)

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

const { interval, zip } = Rx;
const { map } = RxOperators;

zip(event$, interval(20)).pipe(map(([item, i]) => item));

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

Напримерzip работает в вашем примере с эмиссиями в 20, 30, 50, 60 с минимальной задержкой 20.
zip не будет отлично работать с эмиссиями в 20, 30, 65, 70 с минимальной задержкой 20.

https://rxviz.com/v/2ORZLllO

0 голосов
/ 10 февраля 2019

Не уверен, есть ли готовый оператор, доступный для достижения этого (может быть!), Но вы можете сделать это, отметив время каждым значением и добавив необходимую задержку между:

  1. Отметка времени каждогозначение
  2. Сканирование последовательности и вычисление относительной задержки на основе эффективной временной метки предыдущего значения
  3. delay каждое значение по соответствующему количеству
  4. concat результирующая последовательность

Вот rxviz , иллюстрирующий это.Код выглядит так:

const minTimeBetween = 800

events.pipe(
  timestamp(),
  scan((a, x) => ({
    ...x,
    delayBy: a === null
      ? 0
      : Math.max(0, minTimeBetween - (x.timestamp - (a.timestamp + a.delayBy)))
  }), null),
  concatMap(x => of(x.value).pipe(
    delay(x.delayBy)
  ))
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...