Javascript 如何在RxJS中选择性地发射热(共享)观测值?
在我的代码中,我有一个hot observable(通过share()操作符传递的cold observable)发出带有标识符的值(即有效负载类型包含一个“id”字符串属性)。在此基础上,一群观察者根据所述id过滤发射值 我现在认为我的代码的性能受到了巨大的影响,因为每个观察者都必须过滤发出的每个值。或者更确切地说,每当我需要一个新的观察者订阅共享的观察者时,就会创建一个新的过滤观察者。代码有点像这样:Javascript 如何在RxJS中选择性地发射热(共享)观测值?,javascript,typescript,rxjs,observable,reactivex,Javascript,Typescript,Rxjs,Observable,Reactivex,在我的代码中,我有一个hot observable(通过share()操作符传递的cold observable)发出带有标识符的值(即有效负载类型包含一个“id”字符串属性)。在此基础上,一群观察者根据所述id过滤发射值 我现在认为我的代码的性能受到了巨大的影响,因为每个观察者都必须过滤发出的每个值。或者更确切地说,每当我需要一个新的观察者订阅共享的观察者时,就会创建一个新的过滤观察者。代码有点像这样: const source = new Observable(); const shared
const source = new Observable();
const sharedObservable = source.pipe(share());
sharedObservable
.pipe(filter(payload => payload.id === "id1"))
.subscribe(observerOne);
sharedObservable
.pipe(filter(payload => payload.id === "id2"))
.subscribe(observerTwo);
// etc.
class FilteredHotObservable {
constructor(sourceObservable) {
this.observerMap = new Map();
this.source = sourceObservable;
this.source.subscribe(payload => {
const observers = this.observerMap.get(payload.id);
observers.forEach(observer => observer.next(payload));
});
}
subscribe(observer, desiredIdToFilterBy) {
const observers = this.observerMap.get(desiredIdToFilterBy);
observers.push(observer);
}
}
我最初的解决方案是创建我自己类型的热/共享可观察对象,它根据从ID到应该接收有效负载的观察者列表的内部映射来处理过滤。这将减少为每个订阅的观察者运行一些谓词过滤器函数的成本。在可观察的物体下面,看起来像(或模糊地像)这样:
在我开始实施这个方案之前,我想知道是否已经有一个合适的方法来处理这个场景。换句话说,RxJS是否已经有了一种机制(例如,一个特殊的主题、一个奇特的操作符)来促进这种可伸缩的“过滤和共享”观察
免责声明:以上代码片段的名称和语法与我实际所做的并不准确。它们只是本帖的样本。
编辑:
以下是有关使用过滤器
操作符的排放处理延迟的实际数字。对于“PostFilterLatency”,发射的有效载荷由ID过滤,ID对应于共享可观察对象上的单个观察者。对于“PreFilterLatency”,通过id->Observer映射手动过滤发射,然后使用适当的负载调用Observer.next()。这些数字是从有效负载发出到由相应的观察者处理它们所花费的时间(时间以毫秒为单位)
编辑:这里是我用来运行这些测试的代码的一个例子。我建议您调查使用
过滤器是否会导致“巨大的性能损失”。我不相信这会成为瓶颈。如果不是,你就解决了一个不需要解决的问题。另外,FilteredHotObservable
可能不是该类的最佳名称,因为它不履行可观察契约的任何部分。无论如何,FilteredHotObservable
非常类似于在filter
之后放置另一个share
。我不认为是filter
本身造成了性能的影响。事实上,我打了n个电话给它,而我只能打1个(n是观察者的数量)。这是因为源observable只为每个观察者调用observer.next()
,然后观察者调用filter()
(请参阅本文中的第一个代码片段)。如果我可以在源可观察对象中调用observer.next()
之前进行过滤,它会不会将所需的过滤操作数量从O(n)减少到O(1)?我希望这是有意义的,从本质上说,我需要我的共享源observable来充当它向观察者发出的消息的中介。否则,每个观察者都要负责筛选排放物本身。至于你推荐的调查,瓶颈是在这篇文章之前确定的。在添加过滤机制后,我的可观察发射延迟开始出现峰值(请参阅正文中的第一个代码片段)。你是对的,这可能是由于其他原因造成的,但我不确定还有什么地方可以看,因为filter
是在源可观测物发射和观察者接收之间调用的唯一操作符。谢谢您的回复!有什么东西能帮助我们弄清问题的真相吗?你能在你的问题中包括过滤器数量和每个过滤器的观察者数量的指示性数字吗?如果前者较后者低,只需在每个过滤器后放置另一个共享
即可。
ObserverCount PostFilterLatency PreFilterLatency
------------- ----------------- ----------------
1 0 0
10 0 0
100 0.03 0
1000 0.039 0.001
10000 1.1849 0.0005
100000 19.90902 0.002