У меня есть наблюдаемая 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?





Итак, ваша проблема в том, что вы не хотите иметь фиксированный интервал, а после каждого выброса начинаете все с 125*variable.
Вы можете обернуть interval() внутри defer() и повторно подписаться после каждого выпуска, чтобы вызвать его обратный вызов. Это означает, что после каждой эмиссии interval Observable завершится, и repeat() немедленно повторно подпишется на него:
const obs = defer(() => interval(125 * variable)).pipe(
take(1),
repeat(),
takeWhile(...),
tap(...),
map(...)
);
Другое решение может быть таким -
Потому что "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;
}
используйте таймер вместо интервала, и вам не понадобится дубль (1)