Динамическое изменение интервала RxJS

У меня есть наблюдаемая obs с интервалом 125*variable, выполняющая действие каждые 0,125 секунды. Значение variable будет динамически меняться в моей программе.

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

Как я могу изменить интервал моей наблюдаемой, чтобы использовать правильное/обновленное значение variable?

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
1 617
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Итак, ваша проблема в том, что вы не хотите иметь фиксированный интервал, а после каждого выброса начинаете все с 125*variable.

Вы можете обернуть interval() внутри defer() и повторно подписаться после каждого выпуска, чтобы вызвать его обратный вызов. Это означает, что после каждой эмиссии interval Observable завершится, и repeat() немедленно повторно подпишется на него:

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

используйте таймер вместо интервала, и вам не понадобится дубль (1)

Jensen 14.04.2021 16:47
Ответ принят как подходящий

Другое решение может быть таким -

Потому что "variable" меняется на протяжении всей программы. Итак, у нас сначала есть BehaviorSubject, который будет обертывать "variable" как наблюдаемое, а BehaviorSubject будет использоваться для выдачи следующего значения для 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()

Наличие этого гарантирует запуск вашего интервала (с переменной 125 *) при выпуске каждого нового значения 'variable', отменяя предыдущий интервал (об этом позаботится switchMap). Подпишитесь только один раз [повторно подписываться не нужно].

Другой подход к этой проблеме с аналогичной проблемой. Динамически изменять значение интервала внутри задачи, вызываемой по интервалу.

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

Хитрость заключается в использовании наблюдаемого создателя таймера, который будет вызывать новую эмиссию после каждого переопределенного newInterval, захватываемого субъектом 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;
}

Другие вопросы по теме