简体   繁体   English

如何在RxJS中创建切换流?

[英]How to create a toggle stream in RxJS?

I'd like to create a steam that toggles based on keyup and keydown . 我想创建一个基于keyupkeydown切换的流。 The key code is emitted once on a keydown event and emitted again on the keyup event. keydown事件中一次发出密钥代码,在keyup事件中再次发出密钥代码。 I used distinctUntilChanged to prevent multiple key codes from being sent while keydown fires. 我使用distinctUntilChanged来防止在按下keydown时发送多个键代码。 The problem with my code is that I can't do successive keydown and keyup on the same key code because of the distinctUntilChanged . 我的代码的问题在于,由于distinctUntilChanged ,我无法对同一键代码进行连续的keydownkeyup

Currently, pressing and releasing 'a' followed by 'b' works, but not 'a' followed by 'a'. 当前,按下并释放“ a”后跟“ b”的作品,但没有按下“ a”后跟“ a”的作品。

Requirements 要求

What I want to achieve is: 我想要实现的是:

  • when the key is down, do some task 按下键时,执行一些任务
  • when the key is up, stop doing that task 当钥匙按下时,停止执行该任务
  • multiple keys can be down or up (so can't use the keypress event) 多个键可以按下或keypress (因此不能使用keypress事件)
  • different actions are associated with different keys (think of 'a' for action-1 and 'b' for action-2) 不同的操作与不同的键相关联(对于操作1,请考虑“ a”,对于操作2,请考虑“ b”)

Code

var getKeyCode = function(e) { return e.which; }
var target = document.querySelector('body');

var keyDownStream = Rx.Observable.fromEvent(target, 'keydown')
    .distinctUntilChanged(getKeyCode);

var keyUpStream = Rx.Observable.fromEvent(target, 'keyup')
    .distinctUntilChanged(getKeyCode);

var toggleStream = Rx.Observable.merge(keyDownStream, keyUpStream);

toggleStream.subscribe(function(e) {
    console.log(e.which);
});

I used: 我用了:

var toggleStream = Rx.Observable.fromEvent(document.body, 'keydown').filter(function ( e, index ) {
  return index < 1;
}).takeUntil(Rx.Observable.fromEvent(document.body, 'keyup')).repeat();

toggleStream.subscribe(function ( e ) {
 // the task should go here 
 console.log("key down :" + e.which);
});

You can find a jsbin here : http://jsbin.com/xuqasawese/edit?html,js,console,output 您可以在这里找到一个jsbin: http ://jsbin.com/xuqasawese/edit?html,js,console,output

Currently, pressing and releasing 'a' followed by 'b' works, and also 'a' followed by 'a'. 当前,先按下并释放“ a”,再按下“ b”,然后再按下“ a”,再按下“ a”。 However, you can imagine that you press key 'a' and without releasing that key, press another one 'b' and release 'b'. 但是,您可以想象您按下了键“ a”,而没有释放该键,而是按下了另一个“ b”并释放了“ b”。 Then press another key 'c', and your action will be executed. 然后按另一个键“ c”,将执行您的操作。 It's kind of an edge case, but do you have any intended behaviour should that happen? 这是一种极端情况,但是您应该有任何预期的行为发生吗?

Found the solution was to move the distinctUntilChanged to the merged observable and filter by event type and keycode. 发现该溶液是向移动distinctUntilChanged按事件类型和密钥号码到合并的可观察到的和过滤器。 This would ensure that the subscribers are notified once for the keydown event and once for the keyup event for the same key. 这将确保订阅者会收到一次针对keydown的事件,一旦keyup为同一关键事件。

var filterByTypeAndKeyCode = function(e) { return e.type + e.which; }
var target = document.querySelector('body');
var keyUpStream = Rx.Observable.fromEvent(target, 'keyup');
var keyDownStream = Rx.Observable.fromEvent(target, 'keydown');

Rx.Observable.merge(keyDownStream, keyUpStream)
    .distinctUntilChanged(filterByTypeAndKeyCode)
    .subscribe(function(e) {
        console.log(e.which);
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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