如何从数据和门中获取Out observable?
答案 0 :(得分:2)
根据我的理解,当data$
发出真实时你需要gates$
,而data$
则需要缓冲,否则当gates$
再次发出真假时结束,所以......如: / p>
out$ = gates$.switchMap(x => x? data$ : data$.buffer(gates$))
假设:data$
,gates$
是热流(参见此处RestSharp
的含义)。
这未经过测试,但请尝试一下,让我们知道它是否确实有用(或者用你说的代码证明它:-)。逻辑看起来没问题,我只是不确定重入gates$
。希望来自buffer
的内门$ suscription在外部之前发射。如果没有发生这种情况,您将看到与网络停机时间相对应的数据发布暂停。
好吧,如果这不起作用,那么scan
的标准解决方案就会出现。您寻找的行为可以表示为(微小)状态机,具有两种状态:passthrough
和buffering
。您可以使用scan
实现所有此类状态机。
此处scan
解决方案:Hot and Cold observables : are there 'hot' and 'cold' operators?
const gates$ = Rx.Observable.interval(2000)
.map(_ => Math.random() >= 0.5)
.map(x => ({gates: x}))
.share()
const data$ = Rx.Observable.interval(500)
.map(_ => "data"+ _)
.map(x => ({data: x}))
.share()
const out$ = Rx.Observable.merge(gates$, data$).scan((acc, val) => {
if (acc.controlState === 'passthrough'){
if (Object.keys(val).includes('data')) {
return {
controlState : 'passthrough',
bufferedData : [],
out : val.data
}
}
if (Object.keys(val).includes('gates')) {
if (val.gates) {
// gates passing from true to true -> no changes to perform
return {
controlState : 'passthrough',
bufferedData : [],
out : null
}
} else {
// gates passing from true to false, switch control state
return {
controlState : 'buffered',
bufferedData : [],
out : null
}
}
}
}
if (acc.controlState === 'buffered'){
if (Object.keys(val).includes('data')) {
return {
controlState : 'buffered',
bufferedData : (acc.bufferedData.push(val.data), acc.bufferedData),
out : null
}
}
if (Object.keys(val).includes('gates')) {
if (val.gates) {
// gates from false to true -> switch control state and pass the buffered data
return {
controlState : 'passthrough',
bufferedData : [],
out : acc.bufferedData
}
} else {
// gates from false to false -> nothing to do
return {
controlState : 'buffered',
bufferedData : acc.bufferedData,
out : null
}
}
}
}
}, {controlState : 'passthrough', bufferedData : [], out:null})
.filter(x => x.out)
.flatMap(x => Array.isArray(x.out) ? Rx.Observable.from(x.out) : Rx.Observable.of(x.out))
out$.subscribe(_ => console.log(_))
您可以在此处看到完全相同的技术:https://jsfiddle.net/1znvwyzc/
答案 1 :(得分:0)
const gate$ = Rx.Observable.interval(2000)
.map(_ => Math.random() >= 0.5)
.filter(_ => _)
const data$ = Rx.Observable.interval(500)
.map(_ => "data"+ _)
.buffer(gate$)
.flatMap(_ => Rx.Observable.from(_))
data$.subscribe(_ => console.log(_))
门流产生随机的真值和假值(例如,n / w是向上或向下)。我们只发出此流中的真实值
基于此流的truthy值,我们缓冲数据流。
见小提琴 - fiddle。别忘了打开浏览器控制台:)
答案 2 :(得分:0)
受到这篇文章的贡献的启发,以下内容似乎产生了预期的行为:
const ticks$ = gates$.filter(b => b)
const crosses$ = gates$.filter(b => !b)
const tickedData$ = data$.windowToggle(ticks$, _ => crosses$.take(1)).switch()
const crossedDataBuffers$ = data$.bufferToggle(crosses$, _ => ticks$.take(1))
const crossedData$ = Rx.Observable.from(crossedDataBuffers$)
const out$ = tickedData$.merge(crossedData$)
进行游戏
答案 3 :(得分:0)
有条件地延迟数据$的另一种方法是使用delayWhen()这样的
const gate$ = new BehaviorSubject<boolean>(false);
const triggerF = _ => gate$.pipe(filter(v => v));
const out$ = data$
.pipe(delayWhen(triggerF))
.subscribe( (v) => console.log(v));
// then trigger gate$, for instance:
setTimeout(() => gate$.next(true), 5000);
setTimeout(() => gate$.next(false), 10000);