在RXJS中执行“带条件的压缩”的更简单/更惯用的方式?

时间:2018-12-04 17:37:18

标签: functional-programming stream rxjs

我正在尝试在RXJS中压缩两个Observable,在满足特定条件时成对地从每个Observable中获取值。我找到了一种无需使用i即可完成此操作的方法,但我想知道是否有人知道一种更惯用的方法来完成此操作。

Composable

输出:

zip

查看const { zip, merge, Subject } = require("rxjs"); const rxop = require("rxjs/operators"); const a$ = new Subject(); const b$ = new Subject(); // Zipping a$ and b$ on conditional a.n === b.n const zippedWithCondition$ = merge( a$.pipe( rxop.mergeMap(aMsg => b$.pipe( rxop.find(bMsg => aMsg.n === bMsg.n), rxop.map(bMsg => [aMsg, bMsg]) )) ), b$.pipe( rxop.mergeMap(bMsg => a$.pipe( rxop.find(aMsg => aMsg.n === bMsg.n), rxop.map(aMsg => [aMsg, bMsg]) )) ) ); const withConditionSub = zippedWithCondition$.subscribe(msg => { console.log("[ZIPPED WITH CONDITION]", msg); }); a$.next({n: 0, type: "a"}); b$.next({n: 1, type: "b"}); a$.next({n: 1, type: "a"}); a$.next({n: 2, type: "a"}); b$.next({n: 2, type: "b"}); b$.next({n: 0, type: "b"}); a$.next({n: 3, type: "a"}); b$.next({n: 3, type: "b"}); withConditionSub.unsubscribe(); // Zipping a$ and b$ without a conditional const normalZipped$ = zip(a$, b$); const normalZippedSub = normalZipped$.subscribe(msg => { console.log("[NORMAL ZIP]", msg); }); a$.next({n: 0, type: "a"}); // same order as above b$.next({n: 1, type: "b"}); a$.next({n: 1, type: "a"}); a$.next({n: 2, type: "a"}); b$.next({n: 2, type: "b"}); b$.next({n: 0, type: "b"}); a$.next({n: 3, type: "a"}); b$.next({n: 3, type: "b"}); normalZippedSub.unsubscribe(); [ZIPPED WITH CONDITION] [ { n: 1, type: 'a' }, { n: 1, type: 'b' } ] [ZIPPED WITH CONDITION] [ { n: 2, type: 'a' }, { n: 2, type: 'b' } ] [ZIPPED WITH CONDITION] [ { n: 0, type: 'a' }, { n: 0, type: 'b' } ] [ZIPPED WITH CONDITION] [ { n: 3, type: 'a' }, { n: 3, type: 'b' } ] [NORMAL ZIP] [ { n: 0, type: 'a' }, { n: 1, type: 'b' } ] [NORMAL ZIP] [ { n: 1, type: 'a' }, { n: 2, type: 'b' } ] [NORMAL ZIP] [ { n: 2, type: 'a' }, { n: 0, type: 'b' } ] [NORMAL ZIP] [ { n: 3, type: 'a' }, { n: 3, type: 'b' } ] 的每对匹配情况。对于普通的zip,不会发生这种情况,因为消息是乱序的。

那么有没有更好的方法呢?也许可以扩展为在某种条件下压缩任意数量的可观察对象?

1 个答案:

答案 0 :(得分:0)

在您的解决方案中,您正在构建 2n + 2m 可观测对象。换句话说,如果a$发出 m 个值,而b$发出 n 个值,则您正在创建 2n + 2m < / em> 观测值。

要看到这一点,只需将completea$的方法添加到b$到测试数据序列中,就像下面的示例一样

a$.next({n: 0, type: "a"});
b$.next({n: 1, type: "b"});
a$.next({n: 1, type: "a"});
a$.next({n: 2, type: "a"});
b$.next({n: 2, type: "b"});
b$.next({n: 0, type: "b"});
a$.next({n: 3, type: "a"});
b$.next({n: 3, type: "b"});
a$.complete();
b$.complete();
withConditionSub.unsubscribe();

我认为,为了找到一个好的解决方案,您应该同时考虑时间变量来满足要求。例如:“ a$b$总是发出属性,n依次增加1的对象-预计序列中没有空洞-依此类推。

如果无法指定与时间相关的要求,那么很难想象RxJS解决方案