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

RxJs:如何在同一Observable内获取最后发射的值

用RxJS的scan操作符实现状态留存,无需额外Subject

你需要基于Observable上一次的输出结果处理新输入,同时避免重复执行昂贵操作,完全可以用scan操作符来实现,不需要额外的BehaviorSubject。

改造后的代码示例

interface PersonInfo {
  name: string;
  data: string;
}

const names$ = new Subject<string[]>();

// 用scan累积状态,替代原有的BehaviorSubject
const namesData$ = names$.pipe(
  scan((previousPersons: PersonInfo[], currentNames: string[]) => {
    // 保留当前names列表中存在的人员
    const filteredPersons = previousPersons.filter(person => 
      currentNames.includes(person.name)
    );

    // 补充新增的人员,仅在首次遇到该name时调用昂贵操作
    currentNames.forEach(name => {
      if (!filteredPersons.some(person => person.name === name)) {
        filteredPersons.push({ 
          name, 
          data: getPersonData(name) 
        });
      }
    });

    return filteredPersons;
  }, [] as PersonInfo[]) // 初始状态设为空数组
);

const getPersonData = (name: string) => {
  // 昂贵操作,仅首次触发
  console.log(`getPersonsData called by ${name}`);
  return name;
};

为什么scan是最优解

  • scan的核心逻辑就是持续累积Observable的发射值:每次新的names数组到来时,都会自动用上一次处理后的人员列表(累积值)计算新结果,完全匹配你“复用本Observable最后发射值”的需求。
  • 不需要额外维护BehaviorSubject:状态由scan内部自动管理,避免了手动调用next更新外部状态的副作用,代码更简洁可靠。
  • 解决withLatestFrom的问题:scan支持设置初始值(这里是空数组),第一次names$发射时就能正常处理,不会出现“未初始化”或“永远不发射”的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:27:33