Этот ответ может немного утомлять, но с ним ничего не стоит :-).
Поскольку javascript обычно запускается внутри браузера, который является многопоточным, из которых javascript может занимать несколько потоков, не существует концепции «глобального сна», как в однопоточной программе.
Если вы хотите приостановить операцию любым разумным способом, вы можете принять во внимание следующее.
Допустим, вы хотите следующее
function foo(s) {
var j = 1; var k = 1;
sleep(s); // This would be nice right?
window.alert("Sum is : " + (j+k));
}
Фактически становится:
function foo(s) {
var j = 1 ; var k = 1;
setTimeout(s, function() {
window.alert("Sum is : " + (j+k));
});
}
Конечно, проблема в том, что с процедурной точки зрения вы можете захотеть иметь что-то вроде
function foo() {
do stuff;
pause();
do more stuff;
return;
}
function bar() {
foo(10);
window.alert("I want this to happen only after foo()");
}
Проблема в том, что вы действительно не можете этого сделать с помощью setTimeout, как показано выше
Однако вы можете сделать что-то вроде:
function foo(s, afterwards, afterparms) {
var j = 1 ; var k = 1;
setTimeout(s, function() {
window.alert("Sum is : " + (j+k));
afterparms.parm1 = afterparms.parm1.toUpperCase();
afterwards(afterparms);
});
}
function bar() {
foo(10, function() {
window.alert("This will happen after window.alert");
}, { parm1: 'hello', parm2: 'world' } );
}
Обратите внимание, что это только ОДИН способ передать информацию функциям. Вы можете сделать кое-что действительно крутое, если посмотрите соглашения о вызове функций, переменные аргументы и тому подобное
Это раздражает программу, если вы мыслите процедурно. Однако следует помнить о двух вещах, связанных с javascript. Это НЕ процедурный язык, ИЛИ это объектно-ориентированный язык. Javascript - это функциональный язык со сложной моделью управления событиями. Так что вы должны думать в этих терминах.
Это тоже имеет смысл, поскольку типичная машина javascript - это графический интерфейс (веб-браузер), который по своей конструкции не хочет полностью блокировать при попытке что-то обработать. Представьте, что ваш браузер полностью блокируется, пока страница что-то делает, вы хотите задушить программиста, который это делает с вами.
Код Javascript должен иметь природу «запустил и забыл», и если перед продолжением нужно дождаться наступления события, то вам следует обратиться к модели событий javascript.
Несмотря на то, что это неудобное программирование, когда вы хотите сделать что-то тривиальное, есть вероятность, что вы используете паузу для ожидания таким образом, что с самого начала может начаться гонка, и что есть более подходящий способ сделать " эффект ", которого вы пытаетесь достичь.
Если вы опубликуете свой КОНКРЕТНЫЙ случай, возможно, появится дополнительная информация о том, как можно разрешить такую ситуацию.
Ура,
Чтобы уточнить: вопрос заключается в том, чтобы полностью остановить выполнение скрипта на определенное время, а не задерживать выполнение некоторого фрагмента кода, что будет задачей для setTimeout или setInterval.
Чистая реализация sleep () в JavaScript невозможна и нежелательна.
setTimout и setInterval НЕ останавливают выполнение скрипта, как некоторые здесь думают. Просто зарегистрируйте функцию, которую нужно отложить. Остальная часть скрипта продолжит работу, пока ожидает тайм-аут / интервал.
Из-за асинхронной природы JavaScript единственный способ «заблокировать» выполнение любого кода - это очень уродливый и АБСОЛЮТНО НЕ РЕКОМЕНДУЕМЫЙ цикл while, который выполняется в течение заданного промежутка времени. Поскольку сам JavaScript работает в одном потоке (мы не говорим здесь о WebWorkers API ...). Это остановит выполнение любого JS-кода до завершения цикла. Но это действительно плохой стиль ...
Если ваша программа не может работать без чего-то вроде sleep (), возможно, вам стоит пересмотреть свой подход.
Я могу сделать window.showModalDialog и поместить window.close в модальное диалоговое окно с очень маленьким временем setTimeout
Это изобретательно, но оно позволяет пользователю взаимодействовать только с чем-либо в модальный диалог, на время его открытия. Остальная часть браузера остается зависшей, как если бы вы только что вызвали жестокий цикл while (new Date (). GetTime ()
Модальный диалог более благоприятен для циклов ЦП и позволит избежать срабатывания сторожевого таймера времени выполнения скрипта в случае более длительного ожидания, но вам придется сбалансировать это с раздражением отвлекающего мигающего открытого диалогового окна, и неуниверсальная поддержка браузеров и проблема всех, кто ненавидит модальные диалоги!
Это будет похоже на сон на короткий промежуток времени, и я могу вызвать это несколько раз, если нужно. Есть ли другой способ?
Чего вы на самом деле пытаетесь достичь с помощью сна? Без возврата к циклу событий или запуска модального диалога вы не получите никаких обновлений на экране или взаимодействия с пользователем, поэтому я не понимаю, что для вас сделает встроенный сон. Вы, конечно, не можете делать анимацию таким образом.
В Firefox вы получаете генераторы в стиле Python , которые позволят вам написать процесс взаимодействия в процедурном стиле, используя yield
, чтобы при необходимости вернуть управление браузеру. Это может улучшить простоту кода, поскольку вам не нужно переписывать условные и циклические структуры как запомненное состояние в переменных. Однако, поскольку его поддерживают только браузеры Mozilla, вы не сможете использовать его в обозримом будущем.
ETA:
Я хочу написать ORM с api синхронизации, чтобы разработчикам было проще его использовать. Чтобы связать эту асинхронность с api, мне нужно что-то вроде сна.
Простите, в общем случае сделать нельзя. Базовый JavaScript не имеет потоков, сопрограмм или других примитивов, которые могут связывать синхронизацию и асинхронный код.
Спецификация базы данных Web SQL полагается на браузеры, вызывающие вашу функцию обработки результатов (переданную в executeSql ()
) в качестве обратного вызова браузера. Обратные вызовы браузера могут срабатывать только тогда, когда управление передано обратно браузеру, а не внутри синхронного потока выполнения.
Теоретически вы можете открыть modalDialog, выполнить вызов асинхронной базы данных SQL Web внутри окна modalDialog
и заставить modalDialog вернуть результат синхронному коду в скрипты окна вызывающего абонента. Однако в настоящее время нет браузера, поддерживающего как openDatabase
, так и openModalDialog
!
window.setTimeout
или window.setInterval
- практически ваши единственные друзья.
Пример использования setTimeout
для рекурсивного вызова функции, которая устанавливает другой таймаут, выглядит следующим образом
function go() {
if (go.count < 4) {
// logs 1, 2, 3 to firebug console at 1 second intervals
console.log(go.count++);
window.setTimeout(go, 1000);
}
}
go.count = 1;
go();
Вы можете перехватить идентификатор таймаута, чтобы использовать его в window.clearTimeout
если вам нужно очистить таймаут до его завершения.
Обратите внимание, что ни window.setTimeout
ни window.setInterval
не блокируют выполнение другого скрипта - я не верю, что это возможно с JavaScript в его нынешнем обличье. Существуют способы имитации блокировки пользовательского интерфейса, например, использование showModalDialog
или глобального булева blocking
, которые, боюсь, близки к этому.
@Russ Cam верен, setTimeout
- это то, что вы ищете. Однако то, как вы упомянули об этом в вопросе, заставляет меня думать, что может быть некоторая путаница в том, как это используется.
Он не будет блокировать выполнение блока, в котором находится, скорее, он вызовет свою функцию ввода через определенный интервал. В качестве иллюстрации:
function illustration() {
// start out doing some setup code
alert("This part will run first");
// set up some code to be executed later, in 5 seconds (5000 milliseconds):
setTimeout(function () {
alert("This code will run last, after a 5 second delay")
}, 5000);
// This code will run after the timeout is set, but before its supplied function runs:
alert("This will be the second of 3 alert messages to display");
}
При запуске этой функции вы увидите три предупреждающих сообщения с задержкой между вторым и третьим: