作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 RxJS 捕获用户击键,并为每个击键生成一个结果对象,其中包含键、击键的持续时间(时间keyup
和 keydown
事件之间),以及先前笔划之间的间隔(使用 timeInterval
)。请参阅下图了解概述。
到目前为止,我的代码正在运行:Hello
输出 ShiftLeftHELLO
。
但是当我写得更快时(像往常一样),一切都会崩溃,World
输出ShiftLeftShiftLeftOLD
。
您对实现backpressure有什么建议吗? 、缓冲或我的代码中的其他内容来防止这种行为?
(function (document) {
var textarea = document.querySelector("#input");
var keyUpStream = Rx.DOM.keyup(textarea);
var keyDownStream = Rx.DOM.keydown(textarea);
var keyStrokeStream = Rx.Observable.merge(keyDownStream, keyUpStream);
var keystroke = keyStrokeStream.filter((function() {
var keysPressed = {};
return function(e) {
var k = e.which;
if (e.type == 'keyup') {
delete keysPressed[k];
return true;
} else if (e.type == 'keydown') {
if (keysPressed[k]) {
return false;
} else {
keysPressed[k] = true;
return true;
}
}
};
})())
.distinctUntilChanged(function (e){
return e.type + e.which;
})
.timeInterval()
.bufferWithCount(2)
.zip(function (evts){
return {
"ts" : Date.now(),
"key": evts[0].value.code,
"evts" : evts,
"duration" : evts.reduce(function(a, b){
return b.value.timeStamp - a.value.timeStamp;
})
};
}).subscribe(function (e){
console.log(e);
document.querySelector("#output").textContent += e.key.replace("Key", '');
document.querySelector("#console").textContent += JSON.stringify(e);
});
})(document);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"></script>
<h1>KeyStroke</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<div id="output"></div>
<div id="console"></div>
最佳答案
免责声明:这里是 Rxjs 菜鸟。
问题是您的代码期望在同一键按下键后再按下该键。当您快速打字时,您会遇到击键竞争条件,从而导致缓冲区中出现多次按键或按键。不是您在缓冲区中所期望的。
我修改了代码以利用您的过滤功能。该函数仅返回 keyup 事件,并保存相应的 keydown 笔划。这样,您就可以计算过滤函数内的间隔。我非常确定有一个仅使用 RxJS 函数的更优雅的解决方案,但由于您已经在过滤器函数中使用了状态,所以我对其进行了一些修改。
该代码片段现在显示正确的输出。我认为它解决了你的问题,但这不是使用 RxJS 的好方法(正如我所说,我们在过滤器函数中存储状态)。
(function (document) {
var textarea = document.querySelector("#input");
var keyUpStream = Rx.DOM.keyup(textarea);
var keyDownStream = Rx.DOM.keydown(textarea);
var keyStrokeStream = Rx.Observable.merge(keyDownStream, keyUpStream);
var keystroke = keyStrokeStream.filter((function() {
var keysPressed = {};
return function(e) {
var key = e.which;
var result;
if (e.type == 'keyup' && keysPressed.hasOwnProperty(key)) {
e.strokeInterval = Date.now() - keysPressed[key];
delete keysPressed[key];
return true;
} else if (e.type == 'keydown') {
if (!keysPressed.hasOwnProperty(key)) {
keysPressed[key] = Date.now();
}
return false;
}
return false;
};
})())
.map(function (evt){
return {
"ts" : Date.now(),
"key": evt.code,
"duration" : evt.strokeInterval
};
})
.subscribe(function (e){
console.log(e);
document.querySelector("#output").textContent += e.key.replace("Key", '');
document.querySelector("#console").textContent += JSON.stringify(e);
});
})(document);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"></script>
<h1>KeyStroke</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<div id="output"></div>
<div id="console"></div>
关于javascript - 在 RxJ 中使用背压进行击键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36224872/
我是一名优秀的程序员,十分优秀!