Как применить оператор rxjs в зависимости от значения из источника?

Я создаю страницу с несколькими формами и хочу обнаруживать события mousedown, focus и blur для каждой из этих форм.

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

Я создал Observable под названием Interactions $, которое испускает значения, которые являются объектами «Event», такими как mousedown, focus или blur.

Я использую канал для этого Observable, и теперь у меня есть два варианта оператора:

  • debounceTime (100), чтобы обрабатывать только последний из них
  • throttleTime (100), чтобы обрабатывать только первый из них.
      this.interaction$
         .pipe(
            debounceTime(100),
            tap(evt => console.log('processing event' + evt))
         )
         .subscribe();

В идеале я хочу, чтобы события mousedown и focus обрабатывались поверх события размытия, но проблема в том, что при взаимодействиях $ испускает:

  • "mousedown" появляется перед "blur".
  • "focus" испускается после "размытия"

Итак, мой вопрос:

Есть ли способ применить debounceTime () или throttleTime () в зависимости от исходного значения?

РЕДАКТИРОВАТЬ:

Это взаимодействие $ является субъектом, значения которого передаются в этот обработчик событий:

onFieldInteract(field: string, evt: Event) {
    this.interaction$.next(new FormFieldInteraction(field, evt.type));
}

где FormFieldInteraction - это просто класс с двумя строковыми свойствами.

РЕДАКТИРОВАТЬ 2:

В основном я хочу что-то вроде этого, но я не уверен, есть ли для этого какой-либо оператор rxjs:

this.interaction$.pipe(
      // if event.type === 'blur',
      debounceTime(100),
      // else
      throttleTime(100),
      tap(evt => this.fieldInteract.emit(evt))
   ).subscribe();

person Tomás Law    schedule 16.07.2019    source источник
comment
Не могли бы вы поделиться кодом, как вы определилиinteractions$ Observable? Я думаю, что merge будет работать там, но сначала вы должны рассказать, как intercations выглядит.   -  person Patryk Panek    schedule 16.07.2019
comment
Можете ли вы уточнить конкретный вариант использования, почему вам нужно, чтобы this.interaction$ генерировал события другого типа? Можно ли решить вашу проблему, если бы у вас были разные Observables для разных типов событий?   -  person Goga Koreli    schedule 16.07.2019
comment
@GogaKoreli У меня есть this.interaction$, потому что я хотел объединить все 3 события в один источник, чтобы я мог заблокировать / дросселировать их и обрабатывать только одно   -  person Tomás Law    schedule 16.07.2019
comment
Как вы испускаете эти значения? Вы думали о том, чтобы разделить все три наблюдаемых объекта на один с настраиваемой логикой слияния?   -  person Andrii Zelenskyi    schedule 16.07.2019
comment
@AndriiZelenskyi События focus и mousedown исходят из одного и того же экземпляра компонента, поэтому они уже объединены и генерируют только одно за раз. Размытие происходит из того же компонента (класса), но из другого экземпляра, поэтому я могу объединить его только здесь.   -  person Tomás Law    schedule 16.07.2019
comment
@AndriiZelenskyi, настраиваемая логика слияния должна быть аналогична той, на которую ответил Гога Корели, но она все равно не работает на 100%.   -  person Tomás Law    schedule 16.07.2019


Ответы (1)


Я считаю, что нам нужно лучше задуматься над нашей проблемой. Я думаю, что речь идет не об одном простом операторе, но проблема требует лучшего подхода.

Я разделил два случая: один, когда вы получаете размытие, и оставшиеся события.

  1. Посмотрите на blur$, так как this.interaction$ сначала дебонсируется, а затем фильтруется, общий результат таков, что таким образом вы всегда будете получать правильное событие размытия.

  2. Что касается remaining$, здесь у нас есть оставшиеся события, кроме размытия, задушенные, как вы хотели.

Наконец, мы объединяем их вместе, чтобы получить желаемое поведение.

Взгляните на обновленный пример:

const blur$ = this.interaction$.pipe(
  debounceTime(100),
  filter((event) => event.type === 'blur'),
);

const remaining$ = this.interaction$.pipe(
  filter((event) => event.type !== 'blur'),
  throttleTime(100),
);

merge(blur$, remaining$)
  .pipe(tap((evt) => this.fieldInteract.emit(evt)))
  .subscribe();

Вы ищете такого поведения? Скажите мне, и я изменю ответ в соответствии с вашими потребностями.

person Goga Koreli    schedule 16.07.2019
comment
Не совсем потому, что я не хочу просто delay (). Я хочу debounce (), чтобы событие размытия вообще не обрабатывалось, если после размытия возникает другое событие. - person Tomás Law; 16.07.2019
comment
Внесены изменения в сообщение, чтобы все могли лучше понять, в чем на самом деле заключается сценарий использования. - person Tomás Law; 16.07.2019
comment
есть еще одна ситуация, в которой этот подход не работает. Если событие размытия генерируется после оставшегося события, оно все равно пройдет фильтр и будет сгенерировано. - person Tomás Law; 16.07.2019