简体   繁体   English

如何取消订阅或取消可观察到RxJS的大型数组的过滤?

[英]How can I unsubscribe or cancel the filtering of a large array that is an RxJS observable?

My understanding is that an entire array is pushed to a subscriber, unlike say an interval observer that can be unsubscribed/cancelled. 我的理解是,整个数组被推送给订户,这与可以取消订阅/取消的间隔观察器不同。

For example the following cancellation works... 例如,以下取消有效...

 // emit a value every second for approx 10 seconds let obs = Rx.Observable.interval(1000) .take(10) let sub = obs.subscribe(console.log); // but cancel after approx 4 seconds setTimeout(() => { console.log('cancelling'); sub.unsubscribe() }, 4000); 
 <script src="https://unpkg.com/rxjs@5.5.10/bundles/Rx.min.js"></script> 

However, replacing the interval with an array doesn't. 但是,用数组替换间隔不是。

 // emit a range let largeArray = [...Array(9999).keys()]; let obs = Rx.Observable.from(largeArray) let sub = obs.subscribe(console.log); // but cancel after approx 1ms setTimeout(() => { console.log('cancelling'); sub.unsubscribe() }, 1); // ... doesn't cancel 
 <script src="https://unpkg.com/rxjs@5.5.10/bundles/Rx.min.js"></script> 

Does each element need to be made asynchronous somehow, for example by wrapping it in setTimeout(..., 0)? 是否需要以某种方式使每个元素异步,例如将其包装在setTimeout(...,0)中? Perhaps I've been staring at this problem too long and I'm totally off course in thinking that the processing of an array can be cancelled? 也许我一直在盯着这个问题太久了,而我认为可以取消对数组的处理是完全不对的?

When using from(...) on an array all of the values will be emitted synchronously which doesn't allow any execution time to be granted to the setTimeout that you are using to unsubscribe. 在数组上使用from(...)时,所有值将同步发出,这不允许任何执行时间授予要取消订阅的setTimeout Infact, it finishes emitting before the line for the setTimeout is even reached. 实际上,它甚至在到达setTimeout的行之前就完成了发射。 To allow the emits to not hog the thread you could use the async scheduler ( from(..., Rx.Scheduler.async) ) which will schedule work using setInterval . 要使发射不from(..., Rx.Scheduler.async)线程,您可以使用异步调度程序( from(..., Rx.Scheduler.async) ),它将使用setInterval调度工作。

Here are the docs: https://github.com/ReactiveX/rxjs/blob/master/doc/scheduler.md#scheduler-types 这是文档: https : //github.com/ReactiveX/rxjs/blob/master/doc/scheduler.md#scheduler-types

Here is a running example. 这是一个正在运行的示例。 I had to up the timeout to 100 to allow more room to breath. 我不得不将超时时间增加到100,以便有更多的呼吸空间。 This will slow down your execution of-course. 这将减慢您的课程执行速度。 I don't know the reason that you are attempting this. 我不知道您尝试此操作的原因。 We could probably provide some better advice if you could share the exact use-case. 如果您可以共享确切的用例,我们可能会提供一些更好的建议。

 // emit a range let largeArray = [...Array(9999).keys()]; let obs = Rx.Observable.from(largeArray, Rx.Scheduler.async); let sub = obs.subscribe(console.log); // but cancel after approx 1ms setTimeout(() => { console.log('cancelling'); sub.unsubscribe() }, 100); // ... doesn't cancel 
 <script src="https://unpkg.com/rxjs@5.5.10/bundles/Rx.min.js"></script> 

I've marked @bygrace's answer correct. 我已将@bygrace的答案标记为正确。 Much appreciated! 非常感激! As mentioned in the comment to his answer, I'm posting a custom implementation of an observable that does support such cancellation for interest ... 正如他对答案的评论中所述,我正在发布可观察对象的自定义实现,该实现确实支持取消利息...

 const observable = stream => { let timerID; return { subscribe: observer => { timerID = setInterval(() => { if (stream.length === 0) { observer.complete(); clearInterval(timerID); timerID = undefined; } else { observer.next(stream.shift()); } }, 0); return { unsubscribe: () => { if (timerID) { clearInterval(timerID); timerID = undefined; observer.cancelled(); } } } } } } // will count to 9999 in the console ... let largeArray = [...Array(9999).keys()]; let obs = observable(largeArray); let sub = obs.subscribe({ next: a => console.log(a), cancelled: () => console.log('cancelled') }); // except I cancel it here setTimeout(sub.unsubscribe, 200); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM