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

如何在Observable中保留对象结构并拼接items数组

解决RxJS scan算子保留对象结构并拼接items数组的问题

你现在的问题根源在于scan算子里只返回了拼接后的items数组,直接丢失了原对象的a、b属性。要保留完整对象结构,只需要在累加器函数里返回一个完整的新对象即可:

myObservable$.pipe(
  scan((acc, curr) => ({
    // 先展开当前对象的所有属性,确保a、b始终取最新发射的值
    ...curr,
    // 拼接累加器中存储的旧items和当前的新items数组
    items: [...(acc?.items || []), ...curr.items]
  }), {}) // 初始值设为空对象,兼容第一次发射的场景
)

为什么这样写能解决问题?

  1. 保留最新的a、b属性:通过...curr展开当前发射的对象,最终结果里的a和b会一直是最新发射的值(就像你示例里期望的,最终结果的a是second而非first)。
  2. 安全拼接items数组:[...(acc?.items || []), ...curr.items]会把之前累加的items(如果存在的话)和当前的items合并;第一次发射时acc是空对象,acc?.items为undefined,用[]兜底可以避免报错。

类型安全的写法(推荐)

如果你的项目使用TypeScript,建议明确类型来避免隐式any:

// 先定义数据类型
interface Something {
  c: string;
  d: string;
}

interface MyData {
  a: string;
  b: string;
  items: Something[];
}

// 带类型的scan写法
myObservable$.pipe(
  scan((acc: MyData | {}, curr: MyData): MyData => ({
    ...curr,
    items: [...((acc as MyData)?.items || []), ...curr.items]
  }), {})
)

或者给初始值设置符合MyData结构的默认值,进一步简化类型处理:

myObservable$.pipe(
  scan((acc: MyData, curr: MyData) => ({
    ...curr,
    items: [...acc.items, ...curr.items]
  }), { a: '', b: '', items: [] } as MyData)
)

验证你给出的示例

第一次发射对象:{ a: 'first', b: 'first', items: [{ c: 'bla', d: 'bla' }, { c: 'blabla', d: 'blabla' }] }

  • 初始acc是{ a: '', b: '', items: [] },拼接后items为原数组,结果对象的a、b为first。

第二次发射对象:{ a: 'second', b: 'second', items: [{ c: 'second bla', d: 'second bla' }] }

  • acc是第一次的结果,items拼接成[{ c: 'bla', ... }, { c: 'blabla', ... }, { c: 'second bla', ... }],a、b取最新的second,完全符合你期望的结果。

这样处理后,你就能正常通过(myObservable$ | async)?.a、(myObservable$ | async)?.b访问属性,同时items会是拼接后的完整数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:23:11