将可观察的有效载荷拆分为多个可观察的
Posted
技术标签:
【中文标题】将可观察的有效载荷拆分为多个可观察的【英文标题】:Splitting observable payload into multiple observables 【发布时间】:2021-10-13 17:55:30 【问题描述】:我有一个 Apollo 查询,我通过一个 map 操作符来发送对象。例如,name: "doron", color: "red"
。
query$ = this.apollo.watchQuery(query)
我想将其拆分为 2 个可观察对象 - name$
和 color$
,以便 name$
发出名称值,color$
发出颜色值。
我们今天要做的是:
name$ = new Subject();
color$ = new Subject();
query$.valueChanges.subscribe(p =>
name$.next(p.name);
color$.next(p.color);
)
这并不理想,因为我们需要手动取消订阅。此外,它在订阅任何“子”可观察对象之前订阅查询。
如何在不订阅查询的情况下执行此操作?
【问题讨论】:
【参考方案1】:不要将部分 observables 创建为 Subjects
并推送给它们,而是通过从查询映射直接创建它们。
name$ = query.valueChanges.pipe(map((name) => name));
color$ = query.valueChanges.pipe(map((color) => color));
然后您可以轻松地单独取消订阅它们或在async
管道中使用它们。我创建了一个小展示来说明它是如何工作的:Demo
【讨论】:
当我们订阅每个 observable 时会发生什么?那不会触发两次查询吗? 您正在订阅valueChanges
,订阅它不会触发更改。所以很安全【参考方案2】:
您可以分享 OQ observable 并使用 pluck
获取您的价值
const oq = query$.valueChanges.pipe(share());
let name$ = oq.pipe(pluck('name'));
let color$ = oq.pipe(pluck('color'))
【讨论】:
虽然这是一个很好的解决方案,但问题是如果你有 Typescript,它不是类型安全的(据我所知),另一方面,@dallows 是类型安全的 pluck 或使用 map 并不能确保运行时的类型安全。 Typescript 仅在编译时保护类型。所以为了 100% 类型安全,我们必须添加类型检查功能 你是对的,我的错。我以为地图会改变类型 再看我不认为我错了,看看this StackBlitz,当主题是数字类型而不是字符串时它会出错,你也可以看看map
here的源代码
我知道,这就是我的意思,编译时间,这就是为什么我说如果你有打字稿会很有用,就我而言,pluck
不提供那种类型安全【参考方案3】:
虽然 Fan 和 Dallows 都有很好的答案,但我认为两者结合 + 稍作调整会很好:
query$ = query.pipe(
// You won't subscribe to `query` twice (or more).
shareReplay(
// If one of the observables (`query$`, `name$` or `color$`) are subscribed to later on,
// you'll get instantly the last value that was emitted
// (compared to `share` which wouldn't give you the last value if you subscribe too late).
bufferSize: 1,
// Whenever the number of subscribers to the query falls down to 0, it'll automatically unsubscribe from that observable as well.
refCount: true
)
);
name$ = query$.valueChanges.pipe(
map((name) => name)
);
color$ = query$.valueChanges.pipe(
map((color) => color)
);
(下面的解释也写成上面代码的注释)
使用shareReplay
,您不会订阅query
两次(或更多)。
感谢bufferSize: 1
,如果稍后订阅了其中一个可观察对象(query$
、name$
或 color$
),您将立即获得发出的最后一个值(与 share
相比)如果您订阅得太晚,它不会给您最后的价值)。
感谢refCount: true
,每当查询的订阅者数量降至 0 时,它也会自动取消订阅该 observable。
【讨论】:
以上是关于将可观察的有效载荷拆分为多个可观察的的主要内容,如果未能解决你的问题,请参考以下文章
如何将可观察集合绑定到 xamarin 中的 flexlayout?