javascript - How do I conditionally buffer key input based on event in RxJs -


i'm pretty new rxjs , haven't read solution this. more detailed explanation in comments, want process key combination (i think buffer this) when specific key pressed (like pressing "o" wait short time other keys pressed), process key input otherwise (anything other "o" if "o" hasn't been pressed, or 'timeout' "o" has passed).

observable.fromevent(document, 'keydown')   // want continue processing event if user pressed "o99" in series,   // in pressed "o", followed "9" , "9"   // think can buffer   .buffer(() => observable.timer(1000))   .map((e) => 'option-99')   // need pass keys through unbuffered if it's "o" (unless following "o")   // in other words, "o99" buffered or something, "9" not, , processed   .map((e) => e.keycode) 

thanks

you have common case deal with, of event associated action depends on control state (i.e. have basic state machine). basically, if consider 2 control states : simple_key, combo, , 2 events : keyup, , keyuptimer, :

  • in simple_key state
    • if key pressed o, switch combo state
    • if not o, remain in same state, , pass key downstream
    • if timer event, pass null value filtered out downstream
  • in combo state
    • we accumulate key pressed
    • if timer events, revert simple_key state

so, map event action, need know control state in. operator scan allows decide how process event depending on accumulated state.

it (https://jsfiddle.net/cbhmxaas/):

function getkeyfromevent(ev) {return ev.key} function iskeypressediso(ev) {return getkeyfromevent(ev) === 'o'}  const key = 'key'; const timer = 'timer'; const combo = 'combo'; const simple_key = 'whatever'; const timespaninms = 1000; const keyup$ = rx.observable.fromevent(document, 'keyup')   .map(ev => ({event: key, data: getkeyfromevent(ev)})); const keyuptimer$ = keyup$.flatmaplatest(eventstruct =>    rx.observable.of(eventstruct) //    .tap(console.warn.bind(console, 'timer event'))     .delay(timespaninms)     .map(() => ({event : timer, data: null}))     );  rx.observable.merge(keyup$, keyuptimer$) //  .tap(console.warn.bind(console))   .scan((acc, eventstruct) => {     if (acc.control === simple_key) {       if (eventstruct.event === key) {         if (eventstruct.data === `o`) {           return {control: combo, keyorkeys : []}         }         else {           return {control: simple_key, keyorkeys : eventstruct.data}         }       }       else {       // timer event         return {control: simple_key, keyorkeys : null}       }     }     else {       // have 2 states, combo state here       if (eventstruct.event === key) {         return {control: combo, keyorkeys : acc.keyorkeys.concat([eventstruct.data])}       }       else {         // timer event, have 2 events         return {control: simple_key, keyorkeys : acc.keyorkeys}       }     }   }, {control: simple_key, keyorkeys : null}) //  .tap(console.warn.bind(console))   .filter(state => state.keyorkeys) // timer event in simple_key state   .map (({control, keyorkeys}) => {   // here associate action   // if keyorkeys array, have combo   // else have single key   console.log('key(s) pressed', keyorkeys)   return keyorkeys })   .subscribe (console.log.bind(console)) 

Comments