Выдает значение, затем ожидает продолжительности перед следующим выбросом

#rxjs #rxjs6

#rxjs #rxjs6

Вопрос:

Я создаю службу «оповещения». Когда приходит новое предупреждение, я хочу показать предупреждение на время. В течение этого времени я не хочу показывать другие предупреждения, которые могли прийти. Я хочу перейти к следующему оповещению только ПОСЛЕ завершения текущего. Поэтому, по сути, я хочу испустить значение, а затем подождать длительность, прежде чем выдавать следующее значение.

Это может быть представлено как:

 const incomingAlerts$ = interval(1000);

const alerts$ = incomingAlerts$.pipe(
  concatMap((alert) => alert.pipe(delay(3500)))
);
  

Это близко к тому, что я хочу, но задержка ожидает, ПРЕЖДЕ чем выдавать значение. Существует ли оператор или возможная настройка, которая будет выдавать значение, а затем ждать, прежде чем выдавать следующее значение (если оно есть)?

Ответ №1:

Я думаю, что это может быть достигнуто с помощью exhaustMap :

 incomingAlerts$.pipe(
  exhaustMap(
    alert => NEVER
      .pipe(
        startWith(startAlertAction(alert)),
        takeUntil(duration),
        endWith(stopAlertAction(alert))
    )
  )
)
  

При exhaustMap этом новая внутренняя наблюдаемая не будет создана, если текущая внутренняя наблюдаемая не станет неактивной (например completes , / отправляет error уведомление). Если внутренняя наблюдаемая уже активна, то значение из внешней наблюдаемой будет проигнорировано.

Комментарии:

1. Да, но я не хочу, чтобы те значения, которые будут игнорироваться. Я хочу, чтобы они «ставились в очередь», по существу, для отправки через некоторое время

2. @AveryFerrante что, если вы замените exhaustMap на concatMap в моем примере?

Ответ №2:

Что вам нужно сделать, это создать поток, который выдает значение, ожидает некоторое время, а затем завершается.

Вот довольно странный способ сделать это. Вы устанавливаете a timer и filter отключаете его выброс. Теперь у вас есть поток, который ничего не выдает и завершается за 3500 мс. Затем вы startWith получаете свое предупреждение. Вы можете позволить concatMap обрабатывать остальное (оно будет буферизировать значения до завершения timer потока):

 const alerts$ = incomingAlerts$.pipe(
  concatMap(alert => timer(3500).pipe(
    filter(_ => false),
    startWith(alert)
  ))
);