Sleep() в Javascript

Предположим, я хочу заблокировать выполнение Javascript на некоторое время по какой-то странной причине, как я могу это сделать. В JS нет сна(). Pls не говорит делать while() цикл, потому что это плохо. Я могу сделать window.showModalDialog и поместить window.close в модальный диалог с setTimeout очень малого времени, чтобы пользователь не заметил диалог. Это будет похоже на сон в течение небольшого периода времени, и я могу назвать это несколько раз, если это необходимо. Есть ли другой способ?

Чтобы разработать, мой вариант использования заключается в том, что HTML5 SQL Database предоставила async api, но я хочу использовать его для web-сервера samll, для которого магазин никогда не будет большим. Таким образом, нет необходимости в async api, потому что запросы в небольшом магазине будут выполняться на стороне клиента. Поэтому я хочу написать ORM с sync api, чтобы разработчики могли использовать его более легко. Чтобы свести эту асинхронную синхронизацию к api, мне нужно что-то вроде сна.

Ответы

Ответ 1

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 блокировать выполнение других script - я не верю, что это возможно с JavaScript в этом текущем обличье. Существуют способы, которые могут быть закодированы для имитации блокировки пользовательского интерфейса, например, с использованием showModalDialog или с некоторым глобальным blocking логическим значением, которое примерно так же близко, как вы можете получить, я боюсь.

Ответ 2

@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");
}

При запуске этой функции вы увидите три предупреждающих сообщения с задержкой между вторым и третьим:

  • "Эта часть будет работать первой"
  • "Это будет второе из 3 предупреждающих сообщений для отображения"
  • "Этот код будет работать последним, после 5-секундной задержки"

Ответ 3

Чтобы уточнить: вопрос заключается в том, чтобы полностью приостановить выполнение script в течение определенного времени, а не задерживать выполнение какого-либо фрагмента кода, который будет задачей для setTimeout или setInterval.

Чистая реализация sleep() просто невозможна, а также нежелательна в JavaScript.

setTimout и setInterval НЕ останавливают выполнение script, как некоторые люди здесь выглядят сверху. Просто зарегистрируйте функцию, которую нужно запустить отложить. Остальная часть script будет продолжать работать, пока ожидает время ожидания/интервал.

Из-за асинхронного характера JavaScript единственный способ "заблокировать" выполнение любого кода был бы очень уродливым и абсолютно НЕ РЕКОМЕНДУЕМ, пока цикл, который выполняется в течение определенного времени. Поскольку сам JavaScript работает в одном потоке (мы здесь не говорим об API WebWorkers...). Это остановит выполнение любого JS-кода до тех пор, пока этот цикл не завершится. Но это действительно плохой стиль...

Если ваша программа не может работать без чего-то вроде sleep(), возможно, вам следует пересмотреть свой подход.

Ответ 4

Этот ответ может быть немного раздражающим, но голым с ним:-).

Так как 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 есть две вещи, которые нужно запомнить. Это НЕ процедурный язык, NOR - объектно-ориентированный язык. Javascript - это функциональный язык со сложной моделью управления событиями. Поэтому вы должны думать в этих терминах.

Это тоже имеет смысл, поскольку типичная машина javascript - это gui (веб-браузер), который по дизайну не хочет полностью блокировать, пытаясь что-то обработать. Представьте, что ваш браузер полностью блокируется, пока страница что-то делает, вы хотите задушить программиста, который сделает это с вами.

Javascript-код должен быть "огненным и забытым", и если вам нужно дождаться события, прежде чем продолжить, вы должны посмотреть на модель событий javascript.

Хотя это неудобное программирование, когда вы хотите сделать что-то тривиальное, скорее всего, вы используете паузу, чтобы подождать таким образом, чтобы начать с условий гонки, и что есть более подходящий способ сделать "эффект", который вы пытаетесь достичь.

Если вы опубликуете свой ОПРЕДЕЛЕННЫЙ случай, может появиться больше информации о том, как можно решить такую ​​ситуацию.

Приветствия,

Ответ 5

Я могу сделать window.showModalDialog и поместить window.close в модальный диалог с setTimeout очень малого времени

Это изобретательский, но он позволяет только взаимодействовать с кем-либо в модальном диалоговом окне за время, которое он открывает. Остальная часть браузера остается вешенной так же точно, как если бы вы просто вызвали зверский цикл while (new Date().getTime()<t1);.

Модальное диалоговое окно более мягкое в цикле процессора и позволит избежать запуска сторожевого таймера script -execution-time в случае более длинных ожиданий, но вам придется балансировать это с раздражением отвлекающего диалогового окна с проблесковым открытием, а также не универсальную поддержку браузеров и проблему всех, кто ненавидит модальные диалоги!

Это будет похоже на спящий режим в течение небольшого периода времени, и я могу назвать это несколько раз, если это необходимо. Есть ли другой способ?

Чего вы на самом деле пытаетесь достичь спящим? Не возвращаясь к циклу событий или не запуская модальное диалоговое окно, вы не сможете получить какое-либо обновление на экране или взаимодействие с пользователем, поэтому я не вижу, что сделает встроенный сон для вас. Вы, конечно, не можете делать анимацию таким образом.

В Firefox вы получаете Python-стиль generators, который позволит вам написать процесс взаимодействия процедурного стиля с помощью yield для возврата управления в браузер по мере необходимости. Это может улучшить простоту кода, поскольку вам не нужно переписывать условные и циклические структуры в качестве запоминаемого состояния в переменных. Однако, как поддерживают браузеры Mozilla, вы не можете использовать его в дикой природе в обозримом будущем.

ETA:

Я хочу написать ORM с sync api, чтобы разработчики могли использовать его более легко. Чтобы свести эту асинхронную синхронизацию к api, мне нужно что-то вроде сна.

Извините, не может быть сделано в общем случае. У базового JavaScript нет потоков, ко-подпрограмм или других примитивов, которые могут связывать синхронизацию и асинхронный код.

Спецификация базы данных веб-SQL основывается на браузерах, которые вызывают функцию обработки результатов (переданную в executeSql()) в качестве обратного вызова браузера. Обратные вызовы браузера могут запускаться только тогда, когда управление прошло обратно в браузер, а не в синхронном потоке выполнения.

В теории вы можете открыть modalDialog, выполнить асинхронный вызов базы данных Web SQL внутри окна modalDialog и иметь modalDialog вернуть результат в синхронный код в сценариях окна вызова. Однако в настоящее время нет браузера, который поддерживает как openDatabase, так и openModalDialog!

Ответ 6

Я знаю, что этот вопрос немного устарел, но у меня была аналогичная проблема, когда мне нужно было моделировать script, для загрузки на страницу было занято много времени. Я решил решить проблему, создав конечную точку на стороне сервера, которая ждала 5 секунд перед отправкой ответа, а затем добавила тег script в DOM, чтобы указать на это.

Конечно, для этого требуется реализация на стороне сервера, однако она позволяет остановить страницу в любой конкретной точке. Как уже говорили другие, это блокирует весь браузер, а не только ваш script.