rxjs observable changing interval
You can dynamically control the period using a Subject
together with switchMap
and interval
. Whenever the subject emits a value, that value can be used to specify the interval's period:
const t = Date.now();
let subject = new Rx.Subject();
subject
.switchMap(period => Rx.Observable.interval(period))
.do(() => console.log('some action at time T+' + (Date.now() - t)))
.take(8)
.subscribe();
subject.next(50);
setTimeout(() => subject.next(100), 200);
setTimeout(() => subject.next(200), 400);
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
Here's an elegant solution based on RxJS 6:
import { interval, BehaviorSubject } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
export class SomeComponent implements OnInit {
private interval$: BehaviorSubject<number> = new BehaviorSubject(10000);
ngOnInit() {
this.interval$.pipe(
//Assuming that the value provided by the input is in seconds
switchMap(value => interval(value * 1000)),
tap(() => this.doStuff())
)
.subscribe();
}
intervalChanged(value){
console.log(value);
this.interval$.next(value);
}
doStuff(){
console.log("Hi!");
}
}
Template:
<input (input)="intervalChanged($event.target.value)" type="number">
Adding a working example to help the Googlers
let startButton = document.getElementById('start');
let stopButton = document.getElementById('stop');
let updateButton = document.getElementById('update');
let i1 = document.getElementById('i1');
const start$ = Rx.Observable.fromEvent(startButton, 'click');
const stop$ = Rx.Observable.fromEvent(stopButton, 'click');
const update$ = Rx.Observable.fromEvent(updateButton, 'click')
const period = () => (parseInt(i1.value));
Rx.Observable.merge(
start$,
update$,
)
.switchMap(() => {
return Rx.Observable.interval(period()).takeUntil(stop$);
})
.subscribe(res => {
console.log('here in the subscription:' + res);
})
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
<body>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="update">Update</button>
<input id="i1" value=100></input>
</body>