我正在开发一个对时间非常敏感的应用程序,该应用程序使用按键进行用户输入。因为我在这里说的是毫秒,所以我继续尝试了这样的版本:
function start() {
//stim.style.display = "block";
rt_start = new Date().getTime();
response_allowed = 1;
}
function end() {
var t = rt_end - rt_start;
//stim.style.display = "none";
log.innerHTML = t;
i++;
if (i < iterations) {
setTimeout('start();', 1000);
}
}
var rt_start;
var rt_end;
var iterations = 100;
var i = 0;
var response_allowed = 0;
var stim;
var log;
$(document).ready(function() {
document.onkeydown = function(e) {
if (response_allowed == 1) {
rt_end = new Date().getTime();
response_allowed = 0;
end();
}
};
stim = document.getElementById('stim');
log = document.getElementById('log');
start();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="log"></div>
<img src="https://www.gravatar.com/avatar/cfefd93404e6b0eb3cde02b4b6df4e2b?s=128&d=identicon&r=PG&f=1" id="stim" />
而且它工作正常,通常是低于 5 毫秒的计时器(只需按住一个键)。但是一旦我修改代码以显示图像(取消注释这两行),这就会减慢很多,大约 30 毫秒。
有人能告诉我为什么会出现这种情况,以及如何避免这种额外的延迟吗?
谢谢
最佳答案
我建议使用 DOMHighResTimeStamp在可用的地方(对于不提供它的浏览器带有 polyfill)。
这是一个高分辨率时间戳(设计时考虑了精确测量),用于(例如)导航计时和 Web 性能 API(在 Mozilla 开发人员网络中搜索它,因为我不能分享超过两个单个帖子中的链接)。
获取 DOMHighResTimeStamp 的快速方法 - 就像您使用 var ts = new Date().getTime();
获取常规毫秒时间戳一样 - 是:
var ts = performance.now();
正如我上面所说,看看 MDN 上的 Web Performance API。如果您的应用程序确实对时间很敏感,这将非常有帮助。
编辑:
关于您的代码片段,在我看来,如果您按住某个键,您将始终受限于按键事件的分辨率(持续触发,但不是每毫秒触发一次)。如果您使用文本编辑器按下(连续)字符键并检查该字符每秒被写入多少次,您可以很容易地看到这种行为。。我猜这是通过操作系统设置控制的。
您还受限于与 setTimeout/setInterval 相关的“漂移”。您会看到,setTimeout 会在给定的延迟 后将某事 排入队列以供执行,但它不能保证及时执行。这是一个“尽力而为”的场景,如果浏览器正忙于做某事,它会显着漂移。含义:如果您使用 setTimeout 在 1 秒后重新启用 response_allowed
变量,您可以预期它会在“大约”(但不完全)1 秒后重新启用它。
关于Javascript 按键时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26585171/