简体   繁体   中英

With RXJS, how can I get an observable of keys pressed from the first press until the end of a time window?

I'm trying to detect when multiple keypresses happen within a short window of time.

My attempt is:

fromEvent(window, 'keydown').pipe(
    bufferTime(200),
    filter(events => events.length > 1)
);

The issue with my solution is that the events are emitted every 200ms. This means if a user presses a key at the end of a buffer window and another at the start of the next buffer window the multiple key press isn't captured.

What I'd like instead is for the buffer to start on the first key press and to be emitted 200ms after the 1st keypress.

Ideally I'd like to wait another 200ms before allowing another buffer to start.

Any suggestions gratefully received.

Edit: I've settled on the following.

const keydown$ = fromEvent(window, 'keydown').pipe(share());
const src$ = keydown$.pipe(
    buffer(
        keydown$.pipe(
            debounce(() =>
                timer(150)
            )
        )
    )
);

What I'd like instead is for the buffer to start on the first key press and to be emitted 200ms after the 1st keypress.

Based on that, here could be one solution:

const keydown$ = fromEvent(window, 'keydown').pipe(share());

const src$ = keydown$.pipe(
  buffer(
    concat(keydown$.pipe(take(1), ignoreElements()), timer(200)).pipe(repeat())
  ),
);

share() will place a Subject instance between the data consumer and the data producer( keydown events). With this, the source will not be subscribed on every new subscriber.

Let's have a closer look at

concat(keydown$.pipe(take(1), ignoreElements()), timer(200)).pipe(repeat())

With this, the timer( timer(200 ) starts after the first keydown event. In keydown$.pipe(take(1), ignoreElements()) we use ignoreElements because we don't want the buffer to be emitted after the first event, but only after those 200 ms pass.

Finally, repeat() will be used because both observables passed to concat will eventually complete(which also indicates the moment when the accumulated events will be sent). repeat() will re-resubscribe to concat(...) after it completes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM