Rico Kahler
Rico Kahler

Reputation: 19202

Queue events to fire every 350ms with RxJS

I have a keyboard event that causes an animation to play. It's possible for the user to produce more events than the rate that the animation plays so I want to create a queue that will eventually empty firing one by one after a certain amount of delay.

Desired marble diagram:

=================================================

user:    START|a-b-c-----------------------------

result:  START|-350ms--a--350ms--b--350ms--c-----

=================================================

The user fires 3 events rapidly (a b c). After event a fires, 350ms timer starts. After that timer is finishes, the result fires a and starts another 350ms timer. After that timer is done it fires b. Basically, if a timer is in progress, I want to add it to the queue and emit it later. The rate cannot exceed 350ms and I want every event.

I want to throttle the output of the events to 350ms but I don't want to use the throttle operator because I don't want to loose any events (I want a, b, and c to fire).

A Javascript RxJS solution is preferred but I'll accept any answer with Rx operators in any language.

Upvotes: 1

Views: 163

Answers (1)

Phix
Phix

Reputation: 9880

This seems to do the trick:

import { fromEvent, concat, timer } from 'rxjs';
import { tap, concatMap, filter } from 'rxjs/operators';

fromEvent(document, 'keypress')
.pipe(
  filter((e: KeyboardEvent) => e.code === 'Space'),
  concatMap(() => timer(350))
).subscribe(console.log)

Blitz


Edit: The concat() operator is redundant. Removed.

Upvotes: 2

Related Questions