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

RxJS进阶实现:过滤Observable中第n次符合条件的事件

优化方案:用RxJS内置运算符替代外部状态

你的需求是仅在数值>0.9的事件出现第2次(或每第n次)时触发通知,现有实现依赖外部变量highValue跟踪状态,存在副作用且不符合RxJS响应式编程理念。可以通过组合内置运算符实现更简洁、无副作用的方案:

import { interval } from 'rxjs';
import { filter, map, scan, tap } from 'rxjs/operators';

const targetCount = 2; // 可修改为任意n值,比如3表示每第3次触发

interval(100)
  .pipe(
    map(() => Math.random()),
    tap(v => console.log(v)),
    // 筛选符合条件的数值
    filter(v => v > 0.9),
    // 累计符合条件的事件次数,同时保留当前数值
    scan((acc, curr) => ({
      count: acc.count + 1,
      value: curr
    }), { count: 0, value: null }),
    // 仅保留第n次、第2n次...的事件
    filter(({ count }) => count % targetCount === 0),
    // 取出原始数值
    map(({ value }) => value)
  )
  .subscribe(v => {
    console.warn(v);
  });

方案优势:

  • 无外部状态:完全通过RxJS运算符管理状态,避免外部变量带来的副作用和并发问题
  • 可扩展性强:只需修改targetCount,即可切换为捕获第n次或每第n次符合条件的事件
  • 可读性更高:每个运算符职责单一,逻辑清晰,符合响应式编程最佳实践

如果需求是仅捕获第n次事件(一次性),而非每第n次都触发,可简化为:

import { interval } from 'rxjs';
import { filter, map, skip, take, tap } from 'rxjs/operators';

const targetCount = 2;

interval(100)
  .pipe(
    map(() => Math.random()),
    tap(v => console.log(v)),
    filter(v => v > 0.9),
    skip(targetCount - 1), // 跳过前n-1次符合条件的事件
    take(1) // 仅取第n次事件后结束订阅
  )
  .subscribe(v => {
    console.warn(v);
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 14:18:31