a: 1---2-3-4--5---6
b: ------T---------
o: ------1234-5---6
Using RxJS, is there some operator that can accomplish the diagram above? I have stream A which is a random stream of events, given a stream B which has a single true
event, can I have an output stream that doesn't emit anything until that true
event, and then sends everything is had saved up until then and afterwards emits normally?
I thought maybe I could use buffer()
, but it seems like there is no way to do a one time buffer like this with that operator.
答案 0 :(得分:1)
const { concat, interval, of, from } = rxjs;
const { share, delay, toArray, takeUntil, mergeMap } = rxjs.operators;
const waitUntil = signal$ => source$ => {
const sharedSource$ = source$.pipe(share());
return concat(
sharedSource$.pipe(
takeUntil(signal$),
toArray(),
mergeMap(from)
),
sharedSource$
);
}
const stopWaiting$ = of('signal').pipe(delay(2000));
const source$ = interval(500).pipe(
waitUntil(stopWaiting$)
).subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.js"></script>
答案 1 :(得分:1)
我认为@ZahiC的解决方案是正确的,但就我个人而言,我会使用multicast
运算符在单个链中进行操作。
a$.pipe(
multicast(new Subject(), s => concat(
s.pipe(
buffer(b$),
take(1),
),
s
)),
)
multicast
基本上将流分成两部分,其中concat
首先订阅第一个缓冲的对象,直到b$
发出为止。然后,由于take(1)
和concat
再次订阅相同的流,但这次没有缓冲,因此它立即完成。
答案 2 :(得分:0)
这是我使用TypeScript的解决方案:
export const queueUntil = <T>(signal$: Observable<any>) => (source$: Observable<T>) => {
let shouldBuffer = true;
return source$.pipe(
bufferWhen(() => shouldBuffer ? signal$.pipe(
tap(() => shouldBuffer = false),
) : source$),
concatMap(v => v),
);
};
可以这样使用:
a$.pipe(
queueUntil(b$)
)