我有两个可观察者:
-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-|
-13--14--15--16--17--18--19-----20---------21--------------22------23--24-->
第一个包含一些递增的数字,但一段时间后停止(这些是数据库中的游标结果) 第二个是不断增加的数字。包含来自第一个的一些数字,但不要停止发射。 (这些是新插入的数据库数据)
我希望这两个可观察对象看起来像这样一个连续的可观测量:
-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-----22------23--24-->
此可观测数据仅包含每个数字一次,保持排放顺序。
如何使用尽可能少的内存来解决这个问题?
答案 0 :(得分:2)
您可以通过将第一个流连接的第一个流(.concat
)中的所有元素与第二个流(除了.skipWhile
个)之外的元素(最新的一个(.last
){ p>
const a = '-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15'
const b = '-13--14--15--16--17--18--19-----20---------21--------------22------23--24'
const fromMarble = str => Rx.Observable.defer(() => {
console.log('side effect from subscribing to: ' + str);
return Rx.Observable.from(str.split('-').filter(v => v.length));
});
const a$ = fromMarble(a);
const b$ = fromMarble(b);
const distinct$ = Rx.Observable.concat(
a$,
a$.last().switchMap(latest =>
// .skipWhile + .skip(1) => skipWhile but inclusive
b$.skipWhile(v => v !== latest).skip(1)
),
);
distinct$.subscribe(e => console.log(e));
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
此外,如果您在订阅时有副作用(例如,当您订阅时 - 将创建新光标),您可以使用例如const a$ = fromMarble(a).shareReaplay()
为所有订阅者分享该副作用。
您可以阅读有关分享副作用的更多信息:
答案 1 :(得分:2)
我认为这里最好的方法是缓冲b $直到$ stream达到b $,然后发出b $的所有缓冲项并切换到b $。像这样:
const a = '-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15';
const b = '-13--14--15--16--17--18--19-----20---------21--------------22------23--24';
const fromMarble = str => Rx.Observable.from(str.split('-')).concatMap(x => Rx.Observable.of(x).delay(1)).filter(v => v.length).map(x => parseInt(x));
const a$ = fromMarble(a).share();
const b$ = fromMarble(b).share();
const switchingSignal$ = Rx.Observable.combineLatest(a$, b$.take(1), (a, b) => a >= b).filter(x => x).take(1).share();
const distinct$ = Rx.Observable.merge(
a$.takeUntil(switchingSignal$).map(x => x + '(from a)'),
b$.buffer(switchingSignal$).take(1).mergeMap(buffered => Rx.Observable.from(buffered)).map(x => x + '(from b$ buffer)'),
b$.skipUntil(switchingSignal$).map(x => x + '(from b$)')
);
distinct$.subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.0/Rx.js"></script>