我在下面的代码中有一个Rxjs observable(stream
),它发出了可观察量(subjOne
和subjTwo
)。每个内部可观察量可以在任何时间以任何顺序发出它们自己的值。我的任务是从subjOne捕获值,直到subjTwo发出它的第一个值。
const subjOne = new Subject();
const subjTwo = new Subject();
const stream = Observable.create(observer => {
observer.next(subjOne);
observer.next(subjTwo);
});
stream
.someOperator(subj => subj)
.subscribe(value => console.log('Value: ', value));
示例1:
subjOne
发出值1和2,然后subjTwo
发出值3,然后subjOne
发出4。
输出应为:1,2,3。
示例2:
subjTwo
发出1,然后subjOne
发出2。
输出应为1。
switchMap不适合此处,因为只要从subjOne
发出subjTwo
,它就会从stream
中删除值。关于如何实现这一点的任何想法?感谢。
更新:在我的实际案例中,不仅有两个内部可观察对象 - subjOne
和subjTwo
- 而且是一个恒定的流,因此需要手动编码{{ 1}}不是一个可行的选择。
答案 0 :(得分:3)
我认为这可以满足您的需求:
// scan to let us keep combining the previous observable
// with the next observable
source
.scan((current, next) => {
// takeUntil to stop current when next produces
const currentUntil = current.takeUntil(next);
// now merge current with next
return currentUntil.merge(next)
}, Rx.Observable.empty())
// switch to the most recent version of the combined inner observables
.switch();
请注意,只有内部可观察对象 hot 时,这才能正常工作。如果它们是冷可观察的,则需要更多代码才能实现。
答案 1 :(得分:0)
听起来你正在寻找takeUntil
。
takeUntil
侦听一个流,直到第二个流发出。所以对于你的例子
// Emits every second
const source = Observable.timer(0, 1000);
// Emits once after 3 seconds
const canceller = Observable.timer(3000);
source
// Takes from the source until this stream emits
.takeUntil(canceller)
.subscribe({
next: x => console.log(`Value ${x}`),
complete: () => console.log('Done')
});
// Value 0 -> 0 seconds
// Value 1 -> 1 seconds
// Value 2 -> 2 seconds
// Done -> 3 seconds
答案 2 :(得分:0)
您可以将两个主题分开,然后将它们与takeUntil
:
const subjOne = new Subject();
const subjTwo = new Subject();
const stream = Observable.create(observer => {
observer.next(subjOne);
observer.next(subjTwo);
});
const first$ = stream.take(1).flatMap(x=>x)
const second$ = stream.skip(1).take(1).flatMap(x=>x)
first$.takeUntil(second$).subscribe(...)