2014-10-27 3 views
3

Я работаю над очень чувствительным к времени приложением, которое использует нажатия клавиш для ввода пользователем. Как я говорю миллисекунды здесь, я пошел вперед и попытался версию так:Javascript keydown timing

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 мс.

Может кто-нибудь указать мне направление, почему именно так и как избежать этой дополнительной задержки?

Благодаря

+0

Можете ли вы предоставить jsfiddle? – artm

+0

Замечание: почти нет причин передавать строки в 'setTimeout' /' setInterval' и несколько причин * not * to. Вместо этого передайте ссылку на функцию, которую вы хотите вызвать: 'setTimeout (start, 1000);' –

+0

jsfiddle, похоже, не работает из-за setTimeout? По крайней мере, я не мог заставить его работать раньше, извините. Прохождение строки происходит из-за моего подхода к передаче нескольких функций/действий в исходном скрипте, например. отображение div, изменение его содержимого и т. д. Это различные действия, соединенные вместе. Изменить: действия очень переменные, поэтому нет способа иметь определенную функцию для каждого. –

ответ

1

Я бы рекомендовал использовать DOMHighResTimeStamp, где доступный (с polyfill для браузеров, которые не поддерживают ее).

Это временная метка высокого разрешения (разработанная с точным измерением), которая будет использоваться (например) с помощью интерфейсов навигации и веб-производительности (поиск по ней в Mozilla Developer Network, так как я не могу поделиться больше, чем две ссылки в пределах одного сообщения).

быстрый способ получить DOMHighResTimeStamp - так же, как вы делаете с var ts = new Date().getTime();, чтобы получить очередную миллисекунды метку времени - это:

var ts = performance.now();

Как я уже говорил выше, посмотрите на веб-Performance API в MDN. Это будет очень полезно, если ваше приложение действительно чувствительно к времени.

EDIT:

О вашем фрагменте кода, мне кажется, что если вы держите кнопку нажатой, вы будете всегда ограничены решением KeyDown события (который выстреливает непрерывно, но не каждый milissecond). Вы можете легко увидеть это поведение, если вы нажимаете клавишу символа вниз (непрерывно) с помощью текстового редактора и проверяете, сколько раз в секунду символ , написанный. Это, я думаю, контролируется с помощью настройки ОС.

Вы также ограничены «дрифтом», связанным с setTimeout/setInterval. Видите ли, setTimeout очереди что-то для выполнения после данной задержки, но это не гарантирует своевременное выполнение. Это сценарий «лучшие усилия», и если браузер занят чем-то, он значительно дрейфует. Значение: если вы используете setTimeout для повторного включения переменной response_allowed через 1 секунду, вы можете ожидать, что она снова включит ее после «около» (но не точно) 1 секунду.

+0

Привет, спасибо за ваш ответ. Я уже тестировал performance.now(), но, как представляется, вызывает более высокую нагрузку, чем Date.now() (см. Http://jsperf.com/date-now-vs-new-date-gettime/34). Задержка setTimeout здесь не имеет значения, поскольку я запускаю только время в функции, игнорируя (более или менее) 1000 мс между итерациями. Большая проблема может, как отметил @TJCrowder, в задержке события keydown. Это было (несколько) подтверждено и исправлено с помощью апплета Keydrown (http://jeremyckahn.github.io/keydrown/). Благодаря! –