如何在Observable中保留对象结构并拼接items数组
解决RxJS scan算子保留对象结构并拼接items数组的问题
你现在的问题根源在于scan算子里只返回了拼接后的items数组,直接丢失了原对象的a、b属性。要保留完整对象结构,只需要在累加器函数里返回一个完整的新对象即可:
myObservable$.pipe( scan((acc, curr) => ({ // 先展开当前对象的所有属性,确保a、b始终取最新发射的值 ...curr, // 拼接累加器中存储的旧items和当前的新items数组 items: [...(acc?.items || []), ...curr.items] }), {}) // 初始值设为空对象,兼容第一次发射的场景 )
为什么这样写能解决问题?
- 保留最新的a、b属性:通过
...curr展开当前发射的对象,最终结果里的a和b会一直是最新发射的值(就像你示例里期望的,最终结果的a是second而非first)。 - 安全拼接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
相关产品推荐
相关产品推荐

