我有一个套接字连接,它发出带有标识符的消息。我想为每种消息创建一个单独的可观察对象。我有一些解决方案,但它们都感觉笨拙或存在性能问题。我是RxJS的新手,所以我不知道我可能会遇到的陷阱。
我的第一个直觉是为每种类型创建一个可过滤的可观察对象:
const receive_message = Rx.fromEvent(socket, 'data').pipe(share());
const message_type_a = receive_message.pipe(filter(message => message.type === 'a'));
const message_type_b = receive_message.pipe(filter(message => message.type === 'b'));
const message_type_c = receive_message.pipe(filter(message => message.type === 'c'));
const message_type_d = receive_message.pipe(filter(message => message.type === 'd'));
我认为这会导致性能问题,因为每次收到任何消息时,它都会针对每种消息类型执行此检查。
我考虑过像这样进行多阶段分区:
const receive_message = Rx.fromEvent(socket, 'data');
const [message_type_a, not_a] = receive_message.pipe(partition(message => message.type === 'a'));
const [message_type_b, not_b] = not_a.pipe(partition(message => message.type === 'b'));
const [message_type_c, message_type_d] = not_b.pipe(partition(message => message.type === 'c'));
这太笨拙了,我不确定它的性能是否比过滤器解决方案还要强。
接下来,我尝试使用如下主题:
const message_type_a = new Rx.Subject();
const message_type_b = new Rx.Subject();
const message_type_c = new Rx.Subject();
const message_type_d = new Rx.Subject();
Rx.fromEvent(socket, 'data').subscribe(function (message) {
switch (message.type) {
case 'a':
message_type_a.next(message);
break;
case 'b':
message_type_b.next(message);
break;
case 'c':
message_type_c.next(message);
break;
case 'd':
message_type_d.next(message);
break;
default:
console.log('Uh oh');
}
},
console.log,
function () {
message_type_a.complete();
message_type_b.complete();
message_type_c.complete();
message_type_d.complete();
}
);
同样,这很笨拙,每当我使用主题时,我都会问自己这是否是“ Rx”的做事方式。
理想情况下,我可以执行以下操作:
const [
message_type_a,
message_type_b,
message_type_c,
message_type_d
] = Rx.fromEvent(socket, 'data').pipe(partitionMany(message.type));
那里是否有任何优雅的解决方案,或者像这样的根本性缺陷,我观察到的拆分源的整体方法是否可以观察到?
这是我的第一个问题,所以我希望我做得很好。提前致谢!
答案 0 :(得分:0)
我将您的开关盒解决方案更改为性能更高的解决方案。
const message_type_a = new Rx.Subject();
const message_type_b = new Rx.Subject();
const message_type_c = new Rx.Subject();
const message_type_d = new Rx.Subject();
subjects = {
'a': message_type_a,
'b': message_type_b,
'c': message_type_c,
'd': message_type_d
}
Rx.fromEvent(socket, 'data').pipe(tap(message =>
subjects[message.type].next(message))).subscribe();
答案 1 :(得分:0)
请参见https://www.npmjs.com/package/rx-splice。
我们有完全相同的情况,在我们的情况下,这确实是一个性能问题(使用node --perf
进行了测量)。在阅读您的问题后,我才创建了此程序包,因为共享很重要。让我知道它是否对您有用!
请注意,只有在执行过滤器的选择器功能出现问题时才需要这样做!如拼接自述文件所述:
仅使用惯用的RxJS代码,对于 拼接的用例。但是,如果您正在编写高性能代码 上面观察到的输入$(或更可能是Subject)将是 订阅了hunderth或数千次(X),因此选择器 filter(fn)函数将被调用X次。这可以-并且 实际上确实证明了-成为我们最大的性能瓶颈 应用程序,所以我们编写了splice,它执行索引选择器 每个发射值只有一次。