throttleTime 运算符的配置参数如何工作? (油门配置)
How does throttleTime operator's config parameter work? (ThrottleConfig)
我已经阅读了 throttleTime documentation,但是我没有完全理解运算符。
我知道 throttleTime(1000)
的工作原理。事件到达后将跳过所有后续事件 1 秒,然后再次开始此过程。
我很难理解的是ThrottleConfig
究竟是如何工作的,这是运算符的第三个参数。
throttleTime<T>(
duration: number,
scheduler: SchedulerLike = async,
config: ThrottleConfig = defaultThrottleConfig): MonoTypeOperatorFunction<T>
leading
和 trailing
属性如何改变源 Observable 的功能?
我已经阅读了很多文档,但他们并没有清楚地解释这一点。
所以有四个选项:
{ leading: true, trailing: false }
:
默认选项,在接收事件后跳过指定持续时间的其他事件,然后重复。
{ leading: false, trailing: true }
:
???
{ leading: false, trailing: false }
:
对此进行了测试,Observable 根本没有发出任何东西。
{ leading: true, trailing: true }
:
???
throttleTime
将在收到新值且尚未受到限制时启动新的 节流间隔 (一个不会发出任何项目的时间段) .此节流间隔的长度由您提供的持续时间决定。
在 RxJS 7 中,当在 节流间隔 结束时发出尾随值时,也会启动一个新的 节流间隔 。
leading
和 trailing
指定项目是否应在 节流间隔 .
的开始或结束时发出
leading:
在新的 节流间隔 .
开始时发射一个项目
trailing:
在 节流间隔 .[=24= 结束时发出从源接收到的最后一个项目]
可视化
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----
当 Source observable 不是固定时间间隔内的序列号时,这个问题可能需要对其他场景进行更详细的解释。
官网的解释是针对场景的
{ leading: true, trailing: false },这也是默认行为。
以官方解释为准here
有一个内部定时器,有启用和禁用两种状态。
当定时器启用时,没有值可以通过。
当计时器被禁用时,一旦第一个源值到达(在计时器禁用事件之后),该值就会被转发到可观察输出,然后计时器被启用。它在持续时间参数中指定的时间跨度内保持启用状态。
这里要注意的重要事实是,定时器被禁用的时间跨度不是固定的,取决于源可观察值的到达。 (如下图所示)
我在 thinkrx.io 站点查看了节流时间行为并且能够重现结果,但仍然需要一些时间来追踪确切的行为。附上来自 ThinkRx 网站的带有标记的大理石图像。
请注意,在 ThinkRx 大理石图中,颜色代表可观察值,数字是时间实例。
在图像中,如果是(Leading True)
红色水平标记是启用定时器时(没有值可以通过)
绿色水平标记是定时器被禁用时。请注意定时器被禁用的时间多于或少于 100 毫秒。
最初定时器是禁用的,它允许0通过并变为启用。
100 毫秒后,它会被禁用并保持该状态直到 230,
通过 230 并再次启用,依此类推。
对于Trailing True的配置设置,Timer跨度与Leading True登录完全相同,虽然不是传递第一个值,而是等到100ms结束然后传递最后一个值直到点.
对于两个 true,它传递前导和尾随的两个值
两个false都不传递任何东西。
{ leading: true, trailing: true }
的预期输出在 rxjs 7 中发生了变化:
https://github.com/ReactiveX/rxjs/commit/ea84fc4dce84e32598701f79d9449be00a05352c
现在将确保节流阀之间的间距始终至少为节流量。
因此,如果有尾随发射,油门间隔将立即重复。这使得来自@frido 的例子变成了这样:
source: --0--1-----2--3----4--5-6---7------------8-------9--------
throttle interval: --[~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~
output: --0-----------3-----------6-----------7-----------9-------
我用下面的有效测试用例重新创建了来自@frido 的示例。
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/rxjs@7.1.0/dist/bundles/rxjs.umd.js"></script>
我已经阅读了 throttleTime documentation,但是我没有完全理解运算符。
我知道 throttleTime(1000)
的工作原理。事件到达后将跳过所有后续事件 1 秒,然后再次开始此过程。
我很难理解的是ThrottleConfig
究竟是如何工作的,这是运算符的第三个参数。
throttleTime<T>(
duration: number,
scheduler: SchedulerLike = async,
config: ThrottleConfig = defaultThrottleConfig): MonoTypeOperatorFunction<T>
leading
和 trailing
属性如何改变源 Observable 的功能?
我已经阅读了很多文档,但他们并没有清楚地解释这一点。
所以有四个选项:
{ leading: true, trailing: false }
:
默认选项,在接收事件后跳过指定持续时间的其他事件,然后重复。{ leading: false, trailing: true }
:
???{ leading: false, trailing: false }
:
对此进行了测试,Observable 根本没有发出任何东西。{ leading: true, trailing: true }
:
???
throttleTime
将在收到新值且尚未受到限制时启动新的 节流间隔 (一个不会发出任何项目的时间段) .此节流间隔的长度由您提供的持续时间决定。
在 RxJS 7 中,当在 节流间隔 结束时发出尾随值时,也会启动一个新的 节流间隔 。
leading
和 trailing
指定项目是否应在 节流间隔 .
leading:
在新的 节流间隔 .
trailing:
在 节流间隔 .[=24= 结束时发出从源接收到的最后一个项目]
可视化
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----
当 Source observable 不是固定时间间隔内的序列号时,这个问题可能需要对其他场景进行更详细的解释。
官网的解释是针对场景的 { leading: true, trailing: false },这也是默认行为。
以官方解释为准here
有一个内部定时器,有启用和禁用两种状态。
当定时器启用时,没有值可以通过。
当计时器被禁用时,一旦第一个源值到达(在计时器禁用事件之后),该值就会被转发到可观察输出,然后计时器被启用。它在持续时间参数中指定的时间跨度内保持启用状态。
这里要注意的重要事实是,定时器被禁用的时间跨度不是固定的,取决于源可观察值的到达。 (如下图所示)
我在 thinkrx.io 站点查看了节流时间行为并且能够重现结果,但仍然需要一些时间来追踪确切的行为。附上来自 ThinkRx 网站的带有标记的大理石图像。
请注意,在 ThinkRx 大理石图中,颜色代表可观察值,数字是时间实例。
在图像中,如果是(Leading True)
红色水平标记是启用定时器时(没有值可以通过) 绿色水平标记是定时器被禁用时。请注意定时器被禁用的时间多于或少于 100 毫秒。
最初定时器是禁用的,它允许0通过并变为启用。 100 毫秒后,它会被禁用并保持该状态直到 230, 通过 230 并再次启用,依此类推。
对于Trailing True的配置设置,Timer跨度与Leading True登录完全相同,虽然不是传递第一个值,而是等到100ms结束然后传递最后一个值直到点.
对于两个 true,它传递前导和尾随的两个值
两个false都不传递任何东西。
{ leading: true, trailing: true }
的预期输出在 rxjs 7 中发生了变化:
https://github.com/ReactiveX/rxjs/commit/ea84fc4dce84e32598701f79d9449be00a05352c
现在将确保节流阀之间的间距始终至少为节流量。
因此,如果有尾随发射,油门间隔将立即重复。这使得来自@frido 的例子变成了这样:
source: --0--1-----2--3----4--5-6---7------------8-------9--------
throttle interval: --[~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~~~~~x~~~~~~~
output: --0-----------3-----------6-----------7-----------9-------
我用下面的有效测试用例重新创建了来自@frido 的示例。
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/rxjs@7.1.0/dist/bundles/rxjs.umd.js"></script>