使用RxJS的多个密钥侦听器



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

作为一种暴力方法,我创建了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
});

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

是的,您应该研究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();

IstartWith为空,因为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)

最新更新