[英]RxJS. Combine observables that emit less then 1 second apart
There are two observables that may be emiting together or separately: stream1
and stream2
.有两个 observable 可以一起或单独发射:
stream1
和stream2
。 I need my subscription to fire only if stream2
fires less then 1 second after stream1
does.仅当
stream2
在stream1
之后 1 秒内触发时,我才需要触发订阅。
Any way to achieve that with RxJS?有什么方法可以通过 RxJS 实现这一目标?
You can use a timestamp and withLatestFrom
to decide which values to emit Here I just filter such that only values that meet your condition pass through.您可以使用时间戳和
withLatestFrom
来决定要发出哪些值在这里我只是过滤,以便只有满足您条件的值才能通过。
stream2.pipe(
timestamp(),
withLatestFrom(stream1.pipe(
timestamp(),
startWith({timestamp: 0, value: null})
)),
filter(([s2, s1]) => s2.timestamp - s1.timestamp < 1000),
map(([s2, s1]) => ({
stream1: s1.value,
stream2: s2.value
}))
);
The following solution really will only work with "hot" Observables because I'm subscribing to the second Observable only after the first one emits:以下解决方案仅适用于“热”的 Observable,因为我仅在第一个 Observable 发出后才订阅第二个 Observable:
const stream1$ = timer(1000);
const stream2$ = timer(800);
stream1$
.pipe(
switchMap(val1 => stream2$.pipe(
timeout(1000),
catchError(() => EMPTY),
map(val2 => [val1, val2]),
))
)
.subscribe(console.log);
timeout()
will emit an error when stream2$
doesn't emit in less than 1s
and the error is immediatelly caught by catchError
and ignored. timeout()
将在stream2$
在不到1s
秒内没有发出错误并且错误立即被catchError
捕获并忽略时发出错误。
To use this solution with cold Observables you can turn them into hot.要将此解决方案与冷的 Observable 一起使用,您可以将它们变成热的。
const stream1$ = timer(1000);
const stream2$ = timer(1800);
const stream2$Published = stream2$.pipe(publish()) as ConnectableObservable<any>;
const subscription = stream2$Published.connect();
stream1$
.pipe(
switchMap(val1 => stream2$Published.pipe(
timeout(1000),
catchError(() => EMPTY),
map(val2 => [val1, val2]),
))
)
.subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-mqudah?devtoolsheight=60现场演示: https://stackblitz.com/edit/rxjs-mqudah?devtoolsheight=60
I think this is a rare case where using publish()
is actually useful.我认为这是使用
publish()
实际有用的罕见情况。 Otherwise, a little shorter solution might be like the following that will work with cold Observables as well even though it's not as easy to understand:否则,一个更短的解决方案可能如下所示,它也适用于冷 Observables,即使它不容易理解:
const stream1$ = timer(400);
const stream2$ = timer(1200);
combineLatest([
stream1$.pipe(timestamp()),
stream2$.pipe(timestamp()),
]).pipe(
// Check that stream1$ emited first && stream2$ emited less than 1000ms after stream1$.
filter(([val1, val2]) => (val1.timestamp < val2.timestamp && (val2.timestamp - val1.timestamp) < 1000)),
map(([val1, val2]) => [val1.value, val2.value]),
).subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-yfhyyh?devtoolsheight=60现场演示: https://stackblitz.com/edit/rxjs-yfhyyh?devtoolsheight=60
However, it's probably not very obvious what the filter()
does from quick glance and has some "cognitive comlexity":).但是,可能不是很明显
filter()
快速浏览并具有一些“认知复杂性”:)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.