RxJs如何将两个重叠的observable合并为一个

时间:2017-10-19 20:54:49

标签: merge rxjs rxjs5

我有两个可观察者:

-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-->

此可观测数据仅包含每个数字一次,保持排放顺序。

如何使用尽可能少的内存来解决这个问题?

2 个答案:

答案 0 :(得分:2)

您可以通过将第一个流连接的第一个流(.concat)中的所有元素与第二个流(除了.skipWhile个)之外的元素(最新的一个(.last

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>