I have read the throttleTime documentation, but I don't get the operator fully.
I know how throttleTime(1000)
works. After an event arrives it will skip all subsequent events for 1 second and then start this process again.
What I have trouble to understand is how exactly ThrottleConfig
works, which is the third parameter of the operator.
throttleTime<T>(
duration: number,
scheduler: SchedulerLike = async,
config: ThrottleConfig = defaultThrottleConfig): MonoTypeOperatorFunction<T>
How do leading
and trailing
properties change the functionality of the source Observable?
I have read many documentations but they don't clearly explain this.
So there are four options:
{ leading: true, trailing: false }
:{ leading: false, trailing: true }
:{ leading: false, trailing: false }
:{ leading: true, trailing: true }
:throttleTime
will start a new throttle interval (a time period in which no items will be emitted) when it receives a new value and isn't already throttled. The length of this throttle interval is determined by the duration you supply.
With RxJS 7 a new throttle interval is also started when a trailing value is emitted at the end of a throttle interval.
leading
and trailing
specify whether an item should be emitted at the beginning or end of a throttle interval.
leading:
Emit an item at the beginning of a new throttle interval.
trailing:
Emit the last item received from the source at the end of a throttle interval.
RxJS 6 & 7 - trailing: false
throttleTime(12 ticks, { leading: true, trailing: false })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~]----[~~~~~~~~~~~]---------[~~~~~~~~~~~]-----
output_1: --0----------------4---------------------8-----------------
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~]---------------[~~~~~~~~~~~]--[~~~~~~~~~~~]-
output_2: --0---------------------------2--------------3-------------
throttleTime(12 ticks, { leading: false, trailing: false })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~]----[~~~~~~~~~~~]---------[~~~~~~~~~~~]-----
output_1: -----------------------------------------------------------
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~]---------------[~~~~~~~~~~~]--[~~~~~~~~~~~]-
output_2: -----------------------------------------------------------
RxJS 6 - trailing: true
throttleTime(12 ticks, { leading: true, trailing: true })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~]----[~~~~~~~~~~~]---------[~~~~~~~~~~~]-----
output_1: --0-----------3----4-----------7---------8-----------9-----
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~]---------------[~~~~~~~~~~~]--[~~~~~~~~~~~]-
output_2: --0-----------1---------------2--------------3-----------4-
throttleTime(12 ticks, { leading: false, trailing: true })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~]----[~~~~~~~~~~~]---------[~~~~~~~~~~~]-----
output_1: --------------3----------------7---------------------9-----
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~]---------------[~~~~~~~~~~~]--[~~~~~~~~~~~]-
output_2: --------------1---------------------------2--------------4-
RxJS 7 - trailing: true
throttleTime(12 ticks, { leading: true, trailing: true })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~
output: --0-----------3-----------6-----------7-----------9--------
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~I~~~~~~~~~~~]---[~~~~~~~~~~~]--[~~~~~~~~~~~I~
output_2: --0-----------1---------------2--------------3-----------4-
throttleTime(12 ticks, { leading: false, trailing: true })
source_1: --0--1-----2--3----4--5-6---7------------8-------9---------
throttle interval: --[~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~~~~I~~~~~~~~
output: --------------3-----------6-----------7-----------9--------
source_2: --0--------1------------------2--------------3---4---------
throttle interval: --[~~~~~~~~~~~I~~~~~~~~~~~]---[~~~~~~~~~~~I~~~~~~~~~~~]----
output_2: --------------1---------------------------2-----------4----
The expected output for { leading: true, trailing: true }
has changed in rxjs 7:
https://github.com/ReactiveX/rxjs/commit/ea84fc4dce84e32598701f79d9449be00a05352c
It will now ensure the spacing between throttles is always at least the throttled amount.
So the throttle interval will repeat immediately if there was a trailing emit. This makes the example from @frido change to something like this:
source: --0--1-----2--3----4--5-6---7------------8-------9--------
throttle interval: --[~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~
output: --0-----------3-----------6-----------7-----------9-------
I have recreated the example from @frido with a valid test case below.
const testScheduler = new rxjs.testing.TestScheduler((actual, expected) => {
const actualString = JSON.stringify(actual);
const expectedString = JSON.stringify(expected)
console.log(actualString)
console.log(expectedString);
console.log(expectedString === actualString);
});
testScheduler.run((helpers) => {
const { cold, time, expectObservable, expectSubscriptions } = helpers;
const e1 = cold(' --0--1-----2--3----4--5-6---7------------8-------9--------|');
const expected = '--0-----------3-----------6-----------7-----------9-------|';
const e1subs = ' ^---------------------------------------------------------!';
const t = time(' ------------|'); // t = 12
expectObservable(e1.pipe(
rxjs.operators.throttleTime(t, null, { leading: true, trailing: true })
)).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
<script src="https://unpkg.com/[email protected]/dist/bundles/rxjs.umd.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With