本文介绍了保证发射之间的 n 秒,而不用最初等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个事件流,例如(每个 -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

通常带有 trailing: truethrottleTime 最接近,但有时会导致 trailing 输出太接近领先输出.

示例代码可以在

2.ConcatMap 到计时器

将每个项目映射到从给定项目开始并在给定时间后完成的计时器.当计时器完成时,将发出下一项.计时器本身发出的值将被忽略.

const { timer } = Rx;const { concatMap, ignoreElements, startWith } = RxOperators;事件$.pipe(concatMap(item => timer(20).pipe(ignoreElements(), startWith(item))));

3.有间隔的压缩(不是最佳的)

如果您的事件流发出项目的速度比所需的延迟快,您可以使用 zip 在间隔发出时发出事件.

const { interval, zip } = Rx;const { 地图 } = RxOperators;zip(event$, interval(20)).pipe(map(([item, i]) => item));

此方法不能保证在所有情况下每个发出的项目之间 n,例如当间隔大于所需延迟时,事件流中紧跟着一个小间隔.

例如 zip 在您的示例中工作,在 20、30、50、60 发出,最小延迟 20.
zip 在 20, 30, 65, 70 和最小延迟 20 的发射时无法完美工作.

interval 发出的速度比事件进入的速度快时,这些间隔项只会堆积在 zip 中.如果是这种情况,zip 将立即从其堆栈中压缩任何具有已经存在的间隔项的新事件,从而在没有预期延迟的情况下发出事件.

Given an event stream like (each - is 10ms)

--A-B--C-D

With debounceTime(20) we get

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

With throttleTime(20) we get

--A----C--

With throttleTime(20, undefined, {leading: true, trailing: true} we get

--A----CD

How can I instead guarantee that I have that much time between each emit, so for example with 20ms

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

In general the throttleTime with the trailing: true gets closest, but it can sometimes cause the trailing output to be too close to the leading output.

Sample code can be found on rxviz.com

解决方案

1. Concat a delay

Concatenate an empty delay to each item, that doesn't emit anything and only completes after a given time.

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

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

2. ConcatMap to a timer

Map every item to a timer that starts with the given item and completes after a given amount of time. The next item will be emitted when the timer completes. Values emitted by the timer itself are ignored.

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

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

3. Zip with an interval (not optimal)

If your event stream emits items faster than the desired delay you could use zip to emit events when an interval emits.

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

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

This method won't guarantee n seconds between every emitted item in all circumstances, e.g. when there is a gap larger than the desired delay followed by a small gap in the event stream.

E.g zip works in your example with emits at 20, 30, 50, 60 with min delay 20.
zip won't work perfectly with emits at 20, 30, 65, 70 with min delay 20.

When the interval emits faster than events are coming in, those interval items will just pile up inside zip. If this is the case zip will immediately zip any new event with an already present interval item from its stack causing events to be emitted without the intended delay.

这篇关于保证发射之间的 n 秒,而不用最初等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 06:07