'Dynamically Change RxJS Interval

I have an observable obs with an interval 125*variable, completing an action ever 0.125 seconds. The value of variable will change dynamically throughout my program.

 obs = interval(125*variable).pipe(
    takeWhile(() => this.t < moment('2019-04-16T18:00:00')),
    tap(() => {
      if (!this.isPaused) {
        this.t.add(1, 'minutes'); this.time = this.t.format('LLL');
      }
    }),
    map(() => moment(this.time))
  );

How can I change my observable's interval to use the correct/updated variable value?



Solution 1:[1]

So your problem is that you don't want to have fixed interval but rather after each emission start all over with 125*variable.

You can wrap interval() inside defer() and resubscribe after each emission to trigger its callback. This means that after each emission the interval Observable will complete and repeat() will re-subscribe to it immediately:

const obs = defer(() => interval(125 * variable)).pipe(
  take(1),
  repeat(),
  takeWhile(...),
  tap(...),
  map(...)
);

Solution 2:[2]

Another approach for this problem with similar problem. Dynamically change interval value inside task that is call by interval.

export class AppComponent {
  msgs = [];
  monitorDevInterval$ = new BehaviorSubject<number>(2000); // start with 2 sec

  ngOnInit() {
    this.msgs.push("Starting");

    this.monitorDevInterval$
      .pipe(
        switchMap( value => interval( value ) ), 
        tap(n => {
          this.msgs.push("Interval tick " + n.toString() + ' ' +  this.monitorDevInterval$.getValue());
          // Update interval with new value
          this.monitorDevInterval$.next( this.monitorDevInterval$.getValue() + 1000 );
        })
      )      
      .subscribe();
  }
}

Solution 3:[3]

The trick is to use the timer observable creator, which will cause a new emission after each redefined newInterval, the interval$ subject captures the newly defined interval

const interval$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
let newInterval = 1000;

this.interval$.pipe(
  switchMap((duration) => timer(duration)),
  tap(() =>  this.interval$.next(this.newInterval))
).subscribe();

changeInterval(interv: number) {
  this.newInterval = interv;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 martin
Solution 2 Dmitry S.
Solution 3 David Filipe Lopes Domingues