Счетчик RXJS с выходным буфером - PullRequest
0 голосов
/ 29 октября 2019

Я пытаюсь реализовать своего рода счетчик с RXJS. Есть предмет (число), который можно постепенно увеличивать или уменьшать. В конце он должен выдать значение счетчика, которое может быть положительным или отрицательным.

Как показано в приведенном ниже примере, входные данные сбрасываются на одну секунду. Это означает, что наблюдаемое излучает через одну секунду бездействия и возвращает сумму значений.

const mySubject$: Subject<number> = new Subject<number>;

get counter$(): Observable<number> {
  return this.mySubject$.pipe(
    buffer(this.mySubject$.pipe(debounceTime(1000))),
    map(steps => steps.reduce((accumulator, currentValue) => accumulator + currentValue, 0))
  );
}

increment(): void {
  this.mySubject$.next(1);
}

reduce(): void {
  this.mySubject$.next(-1);
}

Пока все хорошо ... Но теперь я хочу показать текущее значение счетчика в реальном времени где-то с приращением/ уменьшить, прежде чем он будет выпущен через секунду. Есть ли способ получить доступ к буферизованному массиву до того, как истечет время ожидания?

Я мог бы создать другую переменную-счетчик вне наблюдаемой и поместить туда значение в tap () перед буфером (). Но похоже, что это не так, как в RXJS?

const mySubject$: Subject<number> = new Subject<number>;
const counter: number = 0;

get counter$(): Observable<number> {
  return this.mySubject$.pipe(
    tap(value => this.counter += value),
    buffer(this.mySubject$.pipe(debounceTime(1000))),
    map(steps => steps.reduce((accumulator, currentValue) => accumulator + currentValue, 0)),
    tap(() => this.counter = 0)
  );
}

Есть идеи для чистого способа, как это сделать?


Цель кода: у меня запущено приложениепо телевизору. Во время потоковой передачи пользователь может «перескочить» с шагом в 30 секунд назад или вперед с помощью двух специальных клавиш на пульте дистанционного управления. Если пользователь нажимает кнопку, например, 3 раза подряд, поток переходит на 90 секунд назад или вперед. Существует задержка в одну секунду между нажатием клавиши до того, как накопленное значение должно сработать. Но каждый раз, когда пользователь нажимает кнопку, появляется видимый вывод (например, тост) о том, сколько секунд будет происходить поиск перехода.

Ответы [ 2 ]

1 голос
/ 29 октября 2019

Вы можете попробовать сканирование, которое выполнит для вас суммирование, так что вы можете запросить его где-нибудь и все же отменить вывод.

get counter$(): Observable<number> {
  return this.mySubject$.pipe(
    scan((acc, delta) => delta ? acc + delta : 0, 0),
    tap((value) => *you can use the total accumulator so far here*),
    debounceTime(1000),
  );
}

Для сброса счетчика вы просто отправляете нулевое значениечерез.

0 голосов
/ 30 октября 2019

Я бы использовал один субъект (_jumpBy$), используемый для запуска команд, и два сопоставляемых наблюдаемых: один (jumpByToShow $) сразу показывает значения, накопленные с помощью scan, другой снимает выбросыво-первых, и после выделения значения обнуляет накопленное значение, заставляя субъекта излучать значение -amount.

Не проверено, надеюсь, это поможет.

  private _jumpBy$ = new Subject<number>();

  // the quantity changing immediately, to be shown on screen
  public jumpByToShow$: Observable<number>;

  // the quantity debounced
  public jumpByToExecute$: Observable<number>;

  constructor(/* ... */) {
    this.jumpByToShow$ = this._jumpBy$.pipe(
      startWith(0),
      scan((amount, newAmount) => (amount + newAmount), 0),
      share()
    );

    this.jumpByToExecute$ = this.jumpByToShow$.pipe(
      debounceTime(1000),
      filter(amount => amount !== 0),
      tap(amount => this._jumpBy$.next(-amount))
    );
  }
...