[Rxjs]如何将多个同步事件分组,并在Rxjs中仅触发订户一次?

[Rxjs]如何将多个同步事件分组,并在Rxjs中仅触发订户一次?,rxjs,Rxjs,我有菱形流依赖项和单个事件转换为多个,然后合并为一个,但会触发多次 我想把它们分成单个输出 我已经找到了一个解决方案,但我不确定这是正确的方法还是反模式的方法 如果我的解决方案可能很脏,那么推荐的方法是什么 原创的 const obs1=新主题(); const obs2=obs1.pipe(map(v=>v+1)); const obs3=obs1.pipe(map(v=>v*2)); const obs4=组合测试(obs1、obs2、obs3); obs4.subscribe(consol

我有菱形流依赖项和单个事件转换为多个,然后合并为一个,但会触发多次

我想把它们分成单个输出

我已经找到了一个解决方案,但我不确定这是正确的方法还是反模式的方法

如果我的解决方案可能很脏,那么推荐的方法是什么

原创的

const obs1=新主题();
const obs2=obs1.pipe(map(v=>v+1));
const obs3=obs1.pipe(map(v=>v*2));
const obs4=组合测试(obs1、obs2、obs3);
obs4.subscribe(console.log);
间隔(2000年)
.管道(取(3))
.认购(obs1);
产出:

(3) [0, 1, 0]
(3) [1, 1, 0]
(3) [1, 2, 0]
(3) [1, 2, 2]
(3) [2, 2, 2]
(3) [2, 3, 2]
(3) [2, 3, 4]
我的解决方案

const obs1=新主题();
const obs2=obs1.pipe(map(v=>v+1));
const obs3=obs1.pipe(map(v=>v*2));
const obs4=组合测试(obs1、obs2、obs3)。管道(
switchMap(v=>of(v,asapScheduler)),
);
obs4.subscribe(console.log);
间隔(2000年)
.管道(取(3))
.认购(obs1);
产出(也预期):


IMO
combineLatest
具有相同源且同步的多个观测值是“反模式”。显然,这是可能发生的,有时你实际上不知道观测值是否同步

您的解决方案完全可以,但我的首选解决方案是使用
去BounceTime(0)
。它将与您的代码完全相同,但更简洁

const obs1 = new Subject<number>();
const obs2 = obs1.pipe(map(v => v + 1));
const obs3 = obs1.pipe(map(v => v * 2));
const obs4 = combineLatest(obs1, obs2, obs3).pipe(
    debounceTime(0)
);
obs4.subscribe(console.log);

interval(2000)
    .pipe(take(3))
    .subscribe(obs1);

如果您只是在转换输入值,为什么不执行以下操作

间隔(2000)
.烟斗(
以(3)为例,
映射(val=>([val,val+1,val*2]),
)
.subscribe(数组=>console.log(数组));
或者您真正的数据源不仅仅是转换

或者,如果您需要所有三个源并希望组合最新的值,
withLatestFrom
可能是一个不错的选择,这也会产生预期的输出:

const obs1=新主题();
const obs2=obs1.pipe(map(v=>v+1));
const obs3=obs1.pipe(map(v=>v*2));
常数obs4=obs1.1管道(
withLatestFrom(obs2、obs3)
);
obs4.subscribe(console.log);
间隔(2000年)
.管道(取(3))
.认购(obs1);

实际上,我并不是仅将obs2和obs3用于生成obs4,这只是一个最小的示例。我在不需要obs3的地方使用obs2。所以我重用obs2来创建obs4。当我想要增强代码的可读性时,我遇到了菱形流依赖。但是将它们同步到一个更新中会出现问题。请参阅我编辑的答案,其中包括
withLatestFrom
,这可能就是您要查找的内容。我测试了它,它看起来只有obs1触发订户,但可以携带来自obs2和obs3的最新数据。如果我只有一个源代码,那么它可以很好地工作,并且实际上与使用一些选择器的根源代码的单个订阅没有什么不同,就像在redux中,我们订阅整个状态一样。但当有多个源时,我可能不知道它们是否同步。所以我的问题可能不够准确。还是谢谢你的回答。如果我想在其他地方重用中间流呢?我应该重用转换函数而不是可观察的吗?是的,重用转换函数是解决问题的好方法,是干净和安全的。如果转换函数的执行次数太多(99.99%的情况下都不会发生),那么有一些技术,比如记忆,可以帮助。。。但这将是一个非常具体的案例。
const obs1 = new Subject<number>();
const obs2 = obs1.pipe(map(v => v + 1));
const obs3 = obs1.pipe(map(v => v * 2));
const obs4 = combineLatest(obs1, obs2, obs3).pipe(
    debounceTime(0)
);
obs4.subscribe(console.log);

interval(2000)
    .pipe(take(3))
    .subscribe(obs1);
const obs1 = new Subject<number>();
const obs4 = obs1.pipe(map((v) => [v, v + 1, v * 2])
obs4.subscribe(console.log);