сон () в JavaScript [дубликат]

14
задан nomind 29 June 2010 в 12:06
поделиться

5 ответов

Этот ответ может немного утомлять, но с ним ничего не стоит :-).

Поскольку 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.

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

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

Ура,

3
ответ дан 1 December 2019 в 07:27
поделиться

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

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

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

Из-за асинхронной природы JavaScript единственный способ «заблокировать» выполнение любого кода - это очень уродливый и АБСОЛЮТНО НЕ РЕКОМЕНДУЕМЫЙ цикл while, который выполняется в течение заданного промежутка времени. Поскольку сам JavaScript работает в одном потоке (мы не говорим здесь о WebWorkers API ...). Это остановит выполнение любого JS-кода до завершения цикла. Но это действительно плохой стиль ...

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

6
ответ дан 1 December 2019 в 07:27
поделиться

Я могу сделать 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 !

3
ответ дан 1 December 2019 в 07:27
поделиться

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, которые, боюсь, близки к этому.

14
ответ дан 1 December 2019 в 07:27
поделиться

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

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

  1. «Эта часть будет запущена первой»
  2. «Это будет второе из трех предупреждений. сообщения для отображения "
  3. " Этот код будет запущен последним после 5-секундной задержки "
9
ответ дан 1 December 2019 в 07:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: