简体   繁体   中英

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?

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(...)
);

Another solution could be like this -

Because "variable" is changing throughout the program. So we first have a BehaviorSubject which will wrap "variable" as an observable and BehaviorSubject will be used to emit the next value for variable -

const variable$ = new BehaviorSubject(1); //you can set initial value as per your need

updateVariable(newValue) {
  this.variable$.next(newValue);
}

this.variable$.pipe(
  switchMap(val => interval(125 * val),
  //now apply your various operators chain as per your need
  takeWhile(),...
  tap(),...
  map()...
).subscribe()

Having this will ensure to start your interval (with 125 * variable) on the emission of each new 'variable' value, canceling the previous interval (switchMap will take care of it). Only subscribe once [there is no need to resubscribe].

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();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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