You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxJS:如何抑制特定时间段内重复触发的相同事件?

问题描述

我需要实现忽略指定时间段内重复触发的事件,但如果相同事件在该时间段外触发,则必须处理。尝试了两种RxJS方案都不满足需求:

  • 方案1(throttleTime):会过滤时间段内的所有事件,哪怕是不同的事件,不符合要求

    // 无法满足需求:时间段内的不同事件也会被过滤,而我需要处理这些事件
    event$.pipe(
      throttleTime(300)
    ).subscribe((event) => console.log(event));
    
  • 方案2(distinctUntilChanged):会永久忽略重复事件,哪怕间隔很久触发,不符合要求

    // 无法满足需求:即使相同事件间隔两分钟触发,也会被永久忽略,而我需要处理这类事件
    event$.pipe(
      distinctUntilChanged((previous, current) => JSON.stringify(previous) === JSON.stringify(current))
    ).subscribe((event) => console.log(event));
    

请问有没有办法结合两者或用其他方式实现需求?


解决方案

可以通过groupBy + throttleTime的组合实现需求:先按事件的唯一标识将事件流分组,再对每个分组单独应用节流逻辑。这样不同事件不会互相干扰,同一事件在指定时间段内只会触发一次,超时后再次触发会被正常处理。

以下是封装好的可复用RxJS操作符:

/**
 * RxJS 操作符:按分组节流事件,确保同一分组的事件在指定时间段内最多触发一次
 * 默认使用 JSON.stringify 对事件进行分组,即完全相同的事件会被归为一组
 *
 * @param duration - 节流的时间窗口(毫秒),默认值 100
 * @param keySelector - 分组键选择函数,返回用于分组的字符串,默认使用 JSON.stringify(event)
 * @returns 可用于 RxJS pipe 的操作符函数
 *
 * 示例:
 * import { throttleGroups } from "rxjs-utils"
 *
 * // 对拥有相同 url 属性的事件进行节流(500ms 内同一 url 只触发一次)
 * rapidEvents$.pipe(
 *      throttleGroups(500, (event) => event.url)
 * ).subscribe((event) => console.log('500ms 内不会重复输出相同 url', event.url));
 *
 * // 对完全相同的事件进行节流(默认 100ms 内同一事件只触发一次)
 * rapidEvents$.pipe(
 *      throttleGroups()
 * ).subscribe((event) => console.log('100ms 内不会重复输出相同事件', event));
 */
export const throttleGroups = (duration: number = 100, keySelector = (event): string => JSON.stringify(event)) => {
    return function<T> (source: Observable<T>): Observable<T> {
        return source.pipe(
            groupBy(keySelector),
            mergeMap((eventGroup$) => eventGroup$.pipe(throttleTime(duration)))
        );
    };
};

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 03:25:58