Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript keydown timing

I am working on a very time-sensitive application that uses key presses for user input. As I am talking milliseconds here, I went ahead and tried a version like this:

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" />

And it works fine, usually sub-5ms timers (just holding down a key). But as soon as I modify the code to display the image (uncommenting the two lines), this slows down a lot to about 30ms.

Can someone point me into the direction why exactly this is the case and how to possibly avoid this additional delay?

Thanks

like image 313
Karsten Sender Avatar asked Jan 21 '26 04:01

Karsten Sender


1 Answers

I would recommend using a DOMHighResTimeStamp where available (with a polyfill for browsers that don't provide it).

It's a high-resolution timestamp (designed with accurate measurement in mind) to be used (e.g.) with the Navigation Timing and Web Performance APIs (search for this in the Mozilla Developer Network, as I can't share more than two links within a single post).

The quick way to get a DOMHighResTimeStamp - much like you do with var ts = new Date().getTime(); to get a regular millisecond timestamp - is:

var ts = performance.now();

As I said above, take a look at the Web Performance API at MDN. It will be very helpful if your application is really time-sensitive.

EDIT:

About your snippet, it seems to me that if you hold a key down, you will be always limited to the resolution of the keydown event (which fires continuously, but not every milissecond). You can easily see this behavior if you press a character key down (continuously) with a text editor and check for how many times per second the character is written. This, I guess, is controlled via an OS setting.

You are also limited to the "drift" associated with setTimeout/setInterval. You see, setTimeout queues something for execution after a given delay, but it does not guarantee timely execution. It's a "best effort" scenario and, if the browser is busy doing something, it will drift significantly. Meaning: if you use a setTimeout to re-enable a response_allowed variable after 1 second, you can expect it to re-enable it after "about" (but not exactly) 1 second.

like image 63
paulojreis Avatar answered Jan 22 '26 18:01

paulojreis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!