Rxjs 从等待到所有来源产生一个值
我以正常方式使用RxJS中的Rxjs 从等待到所有来源产生一个值,rxjs,Rxjs,我以正常方式使用RxJS中的with latest from操作符: var combined = source1.withLatestFrom(source2, source3); …从source2和source3主动收集最近的排放量,并仅在source1排放时排放所有三个值 但我不能保证source2或source3在source1生成值之前会生成值。相反,我需要等到所有三个源都产生至少一个值,然后才能让withLatestFrom执行它的操作 合同需要是:如果source1发出,那么组
with latest from
操作符:
var combined = source1.withLatestFrom(source2, source3);
…从source2
和source3
主动收集最近的排放量,并仅在source1
排放时排放所有三个值
但我不能保证source2
或source3
在source1
生成值之前会生成值。相反,我需要等到所有三个源都产生至少一个值,然后才能让withLatestFrom
执行它的操作
合同需要是:如果source1
发出,那么组合的将始终最终在其他源最终产生时发出。如果source1
在等待其他源时多次发射,我们可以使用最新值并放弃以前的值编辑:作为大理石图:
--1------------2---- (source)
----a-----b--------- (other1)
------x-----y------- (other2)
------1ax------2by--
--1------------2---- (source)
------a---b--------- (other1)
--x---------y------- (other2)
------1ax------2by--
------1--------2---- (source)
----a-----b--------- (other1)
--x---------y------- (other2)
------1ax------2by--
我可以为此创建一个自定义操作符,但我想确保我没有错过一个使用普通操作符的明显方法。感觉就像我想在初始发射时使用combinelatetest
,然后从那时起切换到withLatestFrom
,但我一直不知道如何做到这一点
编辑:最终解决方案的完整代码示例:
var Dispatcher = new Rx.Subject();
var source1 = Dispatcher.filter(x => x === 'foo');
var source2 = Dispatcher.filter(x => x === 'bar');
var source3 = Dispatcher.filter(x => x === 'baz');
var combined = source1.publish(function(s1) {
return source2.publish(function(s2) {
return source3.publish(function(s3) {
var cL = s1.combineLatest(s2, s3).take(1).do(() => console.log('cL'));
var wLF = s1.skip(1).withLatestFrom(s2, s3).do(() => console.log('wLF'));
return Rx.Observable.merge(cL, wLF);
});
});
});
var sub1 = combined.subscribe(x => console.log('x', x));
// These can arrive in any order
// and we can get multiple values from any one.
Dispatcher.onNext('foo');
Dispatcher.onNext('bar');
Dispatcher.onNext('foo');
Dispatcher.onNext('baz');
// combineLatest triggers once we have all values.
// cL
// x ["foo", "bar", "baz"]
// withLatestFrom takes over from there.
Dispatcher.onNext('foo');
Dispatcher.onNext('bar');
Dispatcher.onNext('foo');
// wLF
// x ["foo", "bar", "baz"]
// wLF
// x ["foo", "bar", "baz"]
使用combinelateest
和filter
在找到第一个完整集之前删除元组,然后设置一个变量以停止筛选。变量可以在包装延迟
的范围内,以便正确执行操作(支持重新订阅)。这里是java(但RxJs中存在相同的运算符):
我认为答案大致与您描述的一样,让第一个值为combinelatetest
,然后切换到withLatestFrom
。我的JS是模糊的,但我认为它看起来像这样:
var selector = function(x,y,z) {};
var combined = Rx.Observable.concat(
source1.combineLatest(source2, source3, selector).take(1),
source1.withLatestFrom(source2, source3, selector)
);
var combined = source1.publish(function(s1)
{
return source2.publish(function(s2)
{
return source3.publish(function(s3)
{
return Rx.Observable.concat(
s1.combineLatest(s2, s3, selector).take(1),
s1.withLatestFrom(s2, s3, selector)
);
});
});
});
您可能应该使用publish
来避免多个订阅,因此如下所示:
var selector = function(x,y,z) {};
var combined = Rx.Observable.concat(
source1.combineLatest(source2, source3, selector).take(1),
source1.withLatestFrom(source2, source3, selector)
);
var combined = source1.publish(function(s1)
{
return source2.publish(function(s2)
{
return source3.publish(function(s3)
{
return Rx.Observable.concat(
s1.combineLatest(s2, s3, selector).take(1),
s1.withLatestFrom(s2, s3, selector)
);
});
});
});
或者使用箭头函数
var combined = source1.publish(s1 => source2.publish(s2 => source3.publish(s3 =>
Rx.Observable.concat(
s1.combineLatest(s2, s3, selector).take(1),
s1.withLatestFrom(s2, s3, selector)
)
)));
编辑:
我发现concat
有问题,而with latest from
没有得到值。我认为以下方法可行:
var combined = source1.publish(s1 => source2.publish(s2 => source3.publish(s3 =>
Rx.Observable.merge(
s1.combineLatest(s2, s3, selector).take(1),
s1.skip(1).withLatestFrom(s2, s3, selector)
)
)));
…因此,使用combinelatetest
获取一个值,然后使用with latestfrom
获取其余值,实际上with latestfrom
已经
- 等待每个来源
- 仅当source1发射时发射
- 仅记住最后一条source1消息,而其他源尚未启动
//当源1发出时,其他源已经发出
var source1=Rx.可观测间隔(500).取值(7)
var source2=Rx.可观测间隔(100300).取(10)
var source3=Rx.可观测间隔(200).取值(10)
变量选择器=(a,b,c)=>[a,b,c]
资料来源1
.withLatestFrom(源2、源3、选择器)
.subscribe()
vs
我有类似的要求,但只有2个观察。
我首先使用了switchMap+:
observable1
.switchMap(() => observable2.first(), (a, b) => [a, b])
.subscribe(([a, b]) => {...}));
因此:
- 等待,直到两个观察值都发出一些值
- 仅当第一个观察值已更改时才从第二个观察值中提取值(与CombineTest不同)
- 不挂起第二个可观察对象(因为.first())
在我的例子中,第二个可观察对象是一个ReplaySubject。我不确定它是否适用于其他可观察类型
我认为:
- flatMap可能也会起作用
- 可以扩展这种方法来处理2个以上的观测值
我很惊讶with latest from
不会等待第二次观察。我对接受的答案不太满意,所以我最终找到了另一个解决方案。给猫剥皮有很多方法
我的用例只涉及两个流——一个“请求”流和一个“令牌”流。我希望请求在收到后立即激发,使用最新的令牌。如果还没有令牌,那么它应该等待第一个令牌出现,然后触发所有挂起的请求
我对被接受的答案不太满意,所以我最终找到了另一个解决方案。本质上,我将请求流分为两部分——第一个令牌到达之前和之后。我缓冲第一部分,然后在知道令牌流非空时一次性重新释放所有内容
const first=token$.first()
可观察合并(
请求$.buffer(第一个).mergeAll(),
请求$.skipUntil(第一个)
)
.withLatestFrom(令牌$)
现场查看:用例是什么?你在找zip
?zip
不行,因为这三种来源的产量相差悬殊。用例是source1
通常是一种人机交互,比如点击,其他源从不同的源获取数据——ajax响应、SSE流等等<代码>加入
似乎非常接近:您是否尝试过仅使用withLatestFrom?根据文档和我观察到的行为,withLatestFrom方法实际上是在等待每个源生成。仅使用withLatestFrom即可满足您的全部要求。从另一个角度来看:发布嵌套是处理运算符切换问题的一种有趣的方式。根据我对LatestFrom的经验,它确实会等待每个源生成,但这意味着它会跳过在该状态发生之前发生的任何事件。我遇到了一个与OP类似的问题,S1发出其大部分或全部值,S2发出一个值;我想让它等待S2,然后用该值为每个S1值发射,但它只是跳过最后一个S1值。谢谢,我认为你在这方面做得对。在它周围玩看起来像是concat
懒洋洋地订阅第二个可观察对象,因此with latest from
直到combinelatetest
完成后才累积值。使用merge
而不是急切地订阅