I have a simple component with a single button that starts and pauses a stream of numbers generated by RxJS timer.
import { Component, OnInit } from \'@angul
Here's a custom pause operator that will just accumulate values in a buffer when the pause signal is true
, and emit them one by one when it is false
.
Combine it with a simple tap
operator to toggle the behavior subject pause signal when the value hits a specific condition, and you have something will pause on button click and also pause when the value meets a condition (multiple of 12 in this case):
Here is the pause
operator:
function pause(pauseSignal: Observable) {
return (source: Observable) => Observable.create(observer => {
const buffer = [];
let paused = false;
let error;
let isComplete = false;
function notify() {
while (!paused && buffer.length) {
const value = buffer.shift();
observer.next(value);
}
if (!buffer.length && error) {
observer.error(error);
}
if (!buffer.length && isComplete) {
observer.complete();
}
}
const subscription = pauseSignal.subscribe(
p => {
paused = !p;
setTimeout(notify, 0);
},
e => {
error = e;
setTimeout(notify, 0);
},
() => {});
subscription.add(source.subscribe(
v => {
buffer.push(v);
notify();
},
e => {
error = e;
notify();
},
() => {
isComplete = true;
notify();
}
));
return subscription;
});
}
Here is the usage of it:
const CONDITION = x => (x > 0) && ((x % 12) === 0); // is multiple
this.active$ = new BehaviorSubject(true);
const stream$ = timer(500, 500);
const out$ = stream$.pipe(
pause(this.active$),
tap(value => {
if (CONDITION(value)) {
this.active$.next(false);
}
}));
this.d = out$.subscribe(v => console.log(v));
And a working example: https://stackblitz.com/edit/angular-bvxnbf