具有RxJS的多个键侦听器

问题描述 投票:0回答:1

我有一个物理引擎,该引擎会每帧更新一次,我有一个带有轮子的车辆,我想通过使用一些箭头键来控制。

作为一种蛮力方法,我创建了4个Listeners,每个箭头键都这样一个:

按下键时...

    fromEvent(document, KEY_DOWN)
          .pipe(
            filter(e => e.keyCode === KEYS.UP),
            filter(e => !e.repeat)
          )
          .subscribe(() => {
            ...
            updateSpeed(...)
          });

以及释放键时...

 fromEvent(document, KEY_UP)
      .pipe(filter(e => e.keyCode === KEYS.UP))
      .subscribe(() => {
        ...
      updateSpeed(...) // set speed back to 0
      });

它有效,但是看起来很乏味,因为我必须为每个键(总共8个侦听器)创建一个keydown侦听器和一个keyup侦听器。有没有办法合并事件,有一个单一且更优雅的控制器?

javascript rxjs javascript-events addeventlistener keyboard-events
1个回答
0
投票

是,您应该查看combineLatest或组合运算符(https://scotch.io/tutorials/rxjs-operators-for-dummies-forkjoin-zip-combinelatest-withlatestfrom)之一。

这不是一个完整的答案,但可以帮助您入门

import { combineLatest } from 'rxjs';
...
x = combineLatest(
  fromEvent(document, KEY_DOWN).pipe(
    filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */),
    filter(e => !e.repeat),
    startWith(null),
  ),
  fromEvent(document, KEY_UP).pipe(
    filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */)),
    startWith(null),
  )
).subscribe(([keyDown, keyUp]) => {
    // you have access to keyDown and keyUp events here. Make sure they are truthy since we startWith null and see their values and do the appropriate actions
  });

....
x.unsubscribe();

I startWith为null,因为combineLatest,每个可观察对象必须至少发射一次以启动流,因此它将启动流。您可能需要四处摸索才能获得所需的结果。

此外,由于您正在订阅events,因此从订阅中订阅unsubscribe对您来说非常重要,因为事件不是有限的,并且这可能导致意外行为(即使此代码,订阅也会对每个按键进行反应不是“有效”)。

==========================编辑=================== ===我认为merge甚至是更好的方法。

import { merge } from 'rxjs';

x = merge(
  fromEvent(document, KEY_DOWN).pipe(
    filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */),
    filter(e => !e.repeat),
  ),
  fromEvent(document, KEY_UP).pipe(
    filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */)),
  )
).subscribe(keyUpOrKeyDown => {
  // now you have a handle on the event and can do the appropriate action accordingly
});
....
x.unsubscribe();

我发现这样更好,因为您不需要startWith(null)

© www.soinside.com 2019 - 2024. All rights reserved.