Функция задержка/пауза в Javascript
Ни в базовом языке JavaScript, ни в клиентском JavaScript нет истинной функции ожидания, сна или подобной функции. Однако клиентский JavaScript предоставляет setTimeout(‘jscodehere’, delayInMilliseconds), который позволяет планировать выполнение части скрипта, и setInterval(‘jscodehere’, intervalInMilliseconds), который позволяет периодически выполнять часть скрипта. Так что если вы хотите (псевдокод):
statement1;
wait (someDelay);
statement2;
вы бы вставили код в функцию:
functionstatement1 () {
// ваш код здесь
}
functionstatement2() {
// ваш код здесь
}
и вызовите
statement1();
setTimeout(‘statement2()’, someDelay);
Если вы хотите (псевдокод):
while (someCondition) {
statement 1;
wait(someDelay)
}
Ваш код:
vartid;
функция statement1 () {
// ваш код здесь,
if (!condition)
clearInterval(tid);
}
tid = setInterval(‘statement1()’, someDelay);
Обратите внимание, что и setInterval, и setTimeout возвращают идентификатор таймера, который можно использовать для очистки запланированного выполнения, например:
vartid = setTimeout(‘js code here’, delayInMilliseconds); .
..
clearTimeout(tid);соответственно,
vartid = setInterval(‘js code here’, delayInMilliseconds); .
..
clearInterval(tid);
В приведенном выше решении есть некоторые серьезные ограничения. Во-первых, это делает ваш код более неудобным для написания и трудным для чтения. Еще хуже то, что описанная выше техника вообще не будет работать в определенных ситуациях.
Например, рассмотрим функцию, имеющую состояние (т. е. локальные переменные): может оказаться невозможным разделить ее на 2 функции, как это было вызвано выше, поскольку каждая половина может нуждаться в доступе к полному состоянию.
(Возможно, нельзя хранить состояние в глобальных переменных вместо локальных — скажем, если вы используете функцию рекурсивно.Кроме того, вы не можете передать состояние в виде args второй функции через setTimeout/setInterval, поскольку эти функции принимают только строки в качестве спецификации функции.)
Ниже приведена функция Javascript, которая (с точки зрения вызывающих абонентов) на самом деле является истинной паузой:
/*
* Эта функция не вернется до тех пор, пока (по крайней мере)
* прошло заданное количество миллисекунд.
* Он выполняет цикл «занято-ожидание».
*/
function pause(numberMillis) {
var now = new Date();
varExitTime = now.getTime() + numberMillis;
while (true) {
now = new Date();
if (now.getTime() >ExitTime)
return;
}
}
Основная проблема с этой функцией заключается в том, что она не спит в базовом потоке интерпретатора Javascript. Вместо этого он бесполезно сжигает много циклов процессора. Если у вас современный многопоточный браузер, другие процессы (например, загрузка веб-страницы) все равно должны происходить в других потоках, но они не будут завершаться так быстро, как должны.
Хитрый способ получить эффект истинной паузы, не сжигая циклы процессора, — это использовать модальный диалог с таймаутом, который закрывает модальное диалоговое окно и возобновляет выполнение. Модальный диалог приостанавливает выполнение в коде, который его создал, но позволяет другим потокам продолжать.
/*
* Эта функция не вернется до тех пор, пока (по крайней мере)
* прошло заданное количество миллисекунд.
* Он использует модальный диалог.
*/
function pause(numberMillis) {
vardialogScript =
‘window.setTimeout(‘ +
‘function () { window.close(); },’ + numberMillis + ‘);’;
resultvar =
// Для IE5.
window.showModalDialog(
‘javascript:document.writeln(‘ +
‘»<script>’ + dialogScript + ‘<‘ + ‘/script>»)’);/* Для NN6, но для этого требуется доверенный скрипт.
OpenDialog(
‘javascript:document.writeln(‘ +
‘»<script>’ + dialogScript + ‘<‘ + ‘/script>»‘,
‘pauseDialog’, ‘modal=1,width=10,height=10’);
*/
}
Если вы хотите истинную и эффективную паузу процессора, вам нужно будет использовать реальный язык. Клиентский JavaScript в NN4+ имеет прямой доступ к объектам Java через технологию LiveConnectNN, поэтому ваш Javascript может просто вызвать java.lang.Thread.sleep(timeInMilliSeconds)
ВНИМАНИЕ: если JVM (виртуальная машина Java) еще не запущена, существует дополнительная (несколько секунд) задержка запуска JVM перед выполнением вызова sleep. Последующие звонки затем задержат правильную сумму.
Официально IE не поддерживает Liveconnect. Итак, если вам нужно надежное кроссбраузерное решение, вы можете просто встроить его в общедоступный метод Java-апплета следующим образом:
/**
* Просто вызывает<code>Thread.sleep( (long) timeInMillis )</code>.
* <p>
* Этот метод необходим, потому что Javascript не имеет сна
* функциональность. Кроме того, аргумент должен быть плавающим
* потому что именно таков Числовой тип Javascript
* автоматически преобразуется в когда он вызывает этот метод.
* <p>
* @see<ahref=»http://home.netscape.com/eng/mozilla/3.0/handbook/javascript/livecon.htm#1007805″>Преобразование типов данных</a>
*/
public void sleep(float timeInMillis) вызывает исключение InterruptedException {
Thread.sleep( (long) timeInMillis );
}
Если вышеописанное является членом первого Java-апплета в вашемhtml-файле, вы можете затем вызвать его из вашего Javascript, например:
window.document.applets[0].sleep(2*1000); // sleep for 2 seconds
ПРЕДУПРЕЖДЕНИЕ: вы должны проверить, действительно ли браузер, в котором вы хотите работать, является разумно многопоточным (т. е. запускает интерпретатор Javascript в своем собственном потоке). Вы можете просто проверить это, написав очень большой цикл, который ничего не делает, и посмотреть, может ли браузер все еще делать такие вещи, как реагировать на свой графический интерфейс. Используя этот метод, было сообщено, что NN, по-видимому, запускает интерпретатор JS в том же потоке, что и графический интерфейс браузера.