Что такое JavaScript-версия sleep ()? - PullRequest
1903 голосов
/ 04 июня 2009

Есть ли лучший способ создать sleep в JavaScript, чем следующая pausecomp функция ( взято отсюда )?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

Это не дубликат Сон в JavaScript - задержка между действиями ; Мне нужен реальный сон в середине функции, а не задержка перед выполнением фрагмента кода.

Ответы [ 73 ]

1742 голосов
/ 07 октября 2016

2017 & mdash; Обновление 2019

С 2009 года, когда был задан этот вопрос, JavaScript значительно эволюционировал. Все остальные ответы сейчас устарели или слишком сложны. Вот текущая лучшая практика:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

Вот и все. await sleep(<duration>).

Обратите внимание, что,

  1. await может выполняться только в функциях с префиксом с ключевым словом async или на верхнем уровне вашего сценария в некоторых средах (например, консоль Chrome DevTools или Runkit).
  2. await только приостанавливает текущую async функцию

Две новые функции JavaScript помогли написать эту функцию "сна":

Совместимость

Если по какой-то странной причине вы используете Node старше 7 лет (который достиг конца жизни ) или ориентированы на старые браузеры, async / await все еще можно использовать через Babel (инструмент, который преобразует JavaScript + новые функции в простой старый JavaScript) с плагином transform-async-to-generator.

841 голосов
/ 13 мая 2011

(см. обновленный ответ за 2016 год )

Я думаю, что вполне разумно хотеть выполнить действие, подождать, а затем выполнить другое действие. Если вы привыкли писать на многопоточных языках, у вас, вероятно, есть идея дать выполнение за определенный промежуток времени, пока ваш поток не проснется.

Проблема здесь в том, что JavaScript является однопоточной моделью, основанной на событиях. Хотя в конкретном случае было бы неплохо подождать всего несколько секунд весь двигатель, в целом это плохая практика. Предположим, я хотел использовать ваши функции, когда писал свои собственные? Когда я вызывал твой метод, все мои методы зависали. Если JavaScript может каким-то образом сохранить контекст выполнения вашей функции, сохранить его где-нибудь, затем вернуть обратно и продолжить позже, тогда может произойти сон, но это в основном будет потоковым.

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

Тогда ваш вопрос немного ошибочен. Нельзя спать так, как вы хотите, и вам не следует искать решение, которое вы предлагаете.

621 голосов
/ 04 июня 2009

В JavaScript я переписываю каждую функцию, чтобы она могла завершиться как можно скорее. Вы хотите, чтобы браузер вернулся к управлению, чтобы он мог вносить изменения в DOM.

Каждый раз, когда мне хотелось поспать в середине моей функции, я рефакторинг использовал setTimeout().

Я собираюсь редактировать этот ответ, потому что я нашел это полезным:

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

Написание функции сна просто и стало еще удобнее с обещаниями JavaScript:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});
285 голосов
/ 30 июля 2013

Только для debug / dev , я выкладываю это, если это кому-то полезно

Интересные вещи, в Firebug (и, вероятно, других консолях js), ничего не происходит после нажатия enter, только после указанной продолжительности сна (...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

Пример использования:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }
171 голосов
/ 04 июня 2009

Я согласен с другими авторами, занятый сон - это просто плохая идея.

Однако setTimeout не приостанавливает выполнение, он выполняет следующую строку функции сразу после истечения времени ожидания SET, а не после истечения времени ожидания, поэтому не выполняет ту же задачу, что и спящий режим.

Способ сделать это - разбить вашу функцию на части до и после.

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

Убедитесь, что имена ваших функций по-прежнему точно описывают то, что делает каждый фрагмент (т.е. GatherInputThenWait и CheckInput, а не funcPart1 и funcPart2)

Редактировать

Этот метод позволяет не выполнять выбранные вами строки кода до истечения времени ожидания, в то же время возвращая управление обратно на клиентский ПК, чтобы выполнить все остальное, находящееся в очереди.

Дальнейшее редактирование

Как указано в комментариях, это абсолютно НЕ РАБОТАЕТ в цикле. Вы могли бы сделать какой-нибудь причудливый (уродливый) взлом, чтобы заставить его работать в цикле, но в целом это просто приведет к катастрофическому спагетти-коду.

119 голосов
/ 04 июня 2009

Ради любви к $ DEITY, пожалуйста, не включайте функцию сна в ожидании. setTimeout и setInterval делают все, что вам нужно.

112 голосов
/ 04 ноября 2011

Я знаю, что это старый вопрос, но если (как и я) вы используете Javascript с Rhino, вы можете использовать ...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}
67 голосов
/ 10 июня 2009

Если вы используете jQuery, кто-то на самом деле создал плагин «delay», который является не более чем оболочкой для setTimeout:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

Затем вы можете просто использовать его в строке вызовов функций, как и ожидалось:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');
43 голосов
/ 15 июня 2011

Я тоже искал решение для сна (не для производственного кода, только для dev / tests) и нашел эту статью:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... и вот еще одна ссылка с решениями на стороне клиента: http://www.devcheater.com/

Также, когда вы звоните alert(), ваш код будет также приостановлен, пока отображается предупреждение - нужно найти способ не отображать предупреждение, но получить тот же эффект. :)

30 голосов
/ 03 ноября 2012

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

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}
...