我正在尝试在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,不会发生这种情况,因为消息是乱序的。
那么有没有更好的方法呢?也许可以扩展为在某种条件下压缩任意数量的可观察对象?
答案 0 :(得分:0)
在您的解决方案中,您正在构建 2n + 2m 可观测对象。换句话说,如果a$
发出 m 个值,而b$
发出 n 个值,则您正在创建 2n + 2m < / em> 观测值。
要看到这一点,只需将complete
和a$
的方法添加到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解决方案