如何在 RxJS 中做不同的节流
How to do distinct throttle in RxJS
我花了几天时间,但找不到在 RxJS 中执行 "distinct throttle" 的方法。
假设每个事件在 4 个破折号内完成,"distinct throttle" 将执行如下:
-①-②-①--------①-----|->
[明显油门]
-①-②------------①-----|->
如何使用现有的 RxJS 运算符构建 "distinct throttle"?
您可以使用 groupBy
按值分隔通知,然后可以应用 throttleTime
,然后可以使用 mergeMap
合并分组的可观察对象。像这样:
const { Subject } = rxjs;
const { groupBy, mergeMap, throttleTime } = rxjs.operators;
const source = new Subject();
const result = source.pipe(
groupBy(value => value),
mergeMap(grouped => grouped.pipe(
throttleTime(400)
))
);
result.subscribe(value => console.log(value));
setTimeout(() => source.next(1), 100);
setTimeout(() => source.next(2), 300);
setTimeout(() => source.next(1), 400);
setTimeout(() => source.next(1), 900);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>
distinct
和 throttle
在物品选择方面有 2 个不同的特征。 distinct
将选择第一项,而 throttle
将选择最后一项。
有时您想保持 throttle
的行为。
假设流是:chat-message-edit 事件 携带更新的文本。用户可以在节流期内多次编辑特定消息。
您希望确保始终保留每条消息的最新版本(在不同消息的编辑流中)。
我会遵循的一个可能的解决方案是 the one below
const source$ = from([
{id:1,content:"1a"},
{id:1,content:"1b"},
{id:1,content:"1c"},
{id:2,content:"2a"},
{id:2,content:"2b"},
{id:3,content:"3a"},
{id:3,content:"3b"},
{id:1,content:"1d"},
{id:1,content:"1e"},
{id:4,content:"4a"},
{id:4,content:"4b"},
{id:4,content:"4c"},
{id:4,content:"4e"},
{id:4,content:"4f"},
{id:3,content:"3c"},
{id:3,content:"3d"},
{id:3,content:"3e"}
]).pipe(concatMap((el)=> of(el).pipe(delay(500)) ));
const distinctThrottle = (throttleTime, keySelector)=>
pipe(bufferTime(throttleTime),
concatMap((arr)=>from(arr.reverse()).pipe(distinct(keySelector))
)) ;
let throttledStream = source$.pipe(distinctThrottle(1550, ({id})=>id));
throttledStream.subscribe(console.log);
我花了几天时间,但找不到在 RxJS 中执行 "distinct throttle" 的方法。
假设每个事件在 4 个破折号内完成,"distinct throttle" 将执行如下:
-①-②-①--------①-----|->
[明显油门]
-①-②------------①-----|->
如何使用现有的 RxJS 运算符构建 "distinct throttle"?
您可以使用 groupBy
按值分隔通知,然后可以应用 throttleTime
,然后可以使用 mergeMap
合并分组的可观察对象。像这样:
const { Subject } = rxjs;
const { groupBy, mergeMap, throttleTime } = rxjs.operators;
const source = new Subject();
const result = source.pipe(
groupBy(value => value),
mergeMap(grouped => grouped.pipe(
throttleTime(400)
))
);
result.subscribe(value => console.log(value));
setTimeout(() => source.next(1), 100);
setTimeout(() => source.next(2), 300);
setTimeout(() => source.next(1), 400);
setTimeout(() => source.next(1), 900);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>
distinct
和 throttle
在物品选择方面有 2 个不同的特征。 distinct
将选择第一项,而 throttle
将选择最后一项。
有时您想保持 throttle
的行为。
假设流是:chat-message-edit 事件 携带更新的文本。用户可以在节流期内多次编辑特定消息。
您希望确保始终保留每条消息的最新版本(在不同消息的编辑流中)。
我会遵循的一个可能的解决方案是 the one below
const source$ = from([
{id:1,content:"1a"},
{id:1,content:"1b"},
{id:1,content:"1c"},
{id:2,content:"2a"},
{id:2,content:"2b"},
{id:3,content:"3a"},
{id:3,content:"3b"},
{id:1,content:"1d"},
{id:1,content:"1e"},
{id:4,content:"4a"},
{id:4,content:"4b"},
{id:4,content:"4c"},
{id:4,content:"4e"},
{id:4,content:"4f"},
{id:3,content:"3c"},
{id:3,content:"3d"},
{id:3,content:"3e"}
]).pipe(concatMap((el)=> of(el).pipe(delay(500)) ));
const distinctThrottle = (throttleTime, keySelector)=>
pipe(bufferTime(throttleTime),
concatMap((arr)=>from(arr.reverse()).pipe(distinct(keySelector))
)) ;
let throttledStream = source$.pipe(distinctThrottle(1550, ({id})=>id));
throttledStream.subscribe(console.log);