Rx debounce operator with first and last

2020-07-09 07:32发布

Is there any combination of rx operators so as to get the first and last debounced event?

This is going to be used in master detail scenarios (or even seach scenarios) where we want immediate loading of first selected item and the last after user stops changing selection.

This would prevent the debounce time to be injected when the user navigates slowly but also prevent bursts of changes.

If debounce operator had an option "immediate" like underscore.js debounce functoin then a merge of the 2 versions of debounce operator would generate the needed result.

3条回答
beautiful°
2楼-- · 2020-07-09 08:00

A hybrid operator with UX-friendly behavior: https://www.npmjs.com/package/rx-op-debounce-throttle

Emits first and last items in the batch, plus as much as possible events within the window, separated by at least X ms.

查看更多
家丑人穷心不美
3楼-- · 2020-07-09 08:06

To get the the first debounced element, you can use throttle. To get the last, you can use debounce. You however should make sure that the source you are debouncing or throttling is a hot source as you will apply both operators to the same source. Then if you want both elements in the same observable, then you can just merge the throttled and debounced streams.

For example, calling source$ your source observable:

firstAndLast$ = Rx.Observable.merge(source$.debounce(Xms), source$.throttle(Xms))

This should issue the first item and the last item of a burst in the same stream. Note that in the edge case that this is not a burst but a single value that is occuring within the Xms time period, you might have twice the same value, one at the beginning of the period, and one at the end. A way to protect against that, if that makes sense is to use distinctUntilChanged, so this becomes:

firstAndLast$ = Rx.Observable.merge(source$.debounce(Xms), source$.throttle(Xms)).distinctUntilChanged()
查看更多
混吃等死
4楼-- · 2020-07-09 08:07

Just combining the throttle and debounce as suggested in the previous answer was not enough for me because it periodically emits new events when the throttle time runs out.

const debounced$ = source$.debounceTime(time)
return source$.throttleTime(time)
  .merge(debounced$).distinctUntilChanged()

With a time=30 you would get:

-a-a-a-a-a-a----
-a---a---a----a-

To only get the first and last event with a minimum time in between I used:

const debounced$ = source$.debounceTime(time)
return source$.throttle(() => debounced)
  .merge(debounced$).distinctUntilChanged()

Which results in:

-a-a-a-a-a-a----
-a------------a-
查看更多
登录 后发表回答