Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
579 views
in Technique[技术] by (71.8m points)

rxjs - Guarantee `n` seconds between emit without waiting initially

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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))))
);

enter image description here

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...