Выполнить скрипт после определенной задержки, используя JavaScript

189

Есть ли какой-либо метод JavaScript, аналогичный jQuery delay()или wait()(чтобы задержать выполнение скрипта на определенное время)?

Нияз
источник

Ответы:

189

Есть следующее:

setTimeout(function, milliseconds);

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

Смотрите: Метод окнаsetTimeout() .

Abhinav
источник
3
Это не выражение, которое выполняется, это функция. Ответ @Marius иллюстрирует это.
педрофурла
117
это не задержка, это вилка. Задержка должна работать в той же теме.
DragonLord
13
Это немедленно выполнит function_reference. Для «работы» (асинхронно) это должно быть указано как: setTimeout (function () {MethodToCall ();}, 1000);
Бернулли ИТ
6
Я хочу отметить, что мы говорим о JavaScript; вывод «потоков» или то, что он должен работать «синхронно», может быть технически и семантически верным, но в действительности не вписывается в контекст JavaScript, учитывая, что на самом деле нет способа добиться задержки с помощью любого из этих методов (вы не не создавать "темы" в JS, как на других языках). Кроме того, это не будет немедленно выполнено, function_referenceесли вы не включите (). Т.е. function_referenceпросто это - ссылка; передача function_reference()сразу вызовет функцию немедленно.
Дэнни Буллис
237

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

Вам нужно передать функцию в качестве аргумента, чтобы она вызывалась позже. По сути это означает без скобок за именем. Следующее вызовет оповещение сразу и отобразит «Hello world»:

var a = "world";
setTimeout(alert("Hello " + a), 2000);

Чтобы это исправить, вы можете указать имя функции (как это сделал Флубба) или использовать анонимную функцию. Если вам нужно передать параметр, то вы должны использовать анонимную функцию.

var a = "world";
setTimeout(function(){alert("Hello " + a)}, 2000);
a = "Stack Overflow";

Но если вы запустите этот код, вы заметите, что через 2 секунды всплывающее окно скажет «Hello Stack Overflow». Это связано с тем, что значение переменной a изменилось за эти две секунды. Чтобы через два секунды он сказал «Hello world», вам нужно использовать следующий фрагмент кода:

function callback(a){
    return function(){
        alert("Hello " + a);
    }
}
var a = "world";
setTimeout(callback(a), 2000);
a = "Stack Overflow";

Это будет ждать 2 секунды, а затем всплывающее окно «Привет мир».

Marius
источник
37

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

setTimeout(func, 4000);
function func() {
    alert('Do stuff here');
}
Polsonby
источник
27

Если вы действительно хотите иметь блокирующую (синхронную) delayфункцию (для чего бы то ни было), почему бы не сделать что-то вроде этого:

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>
Марио Вернер
источник
2
Сложность этого решения заключается в том, что оно активно использует процессор, что приводит к увеличению энергопотребления и уменьшению ресурсов, доступных для других потоков / процессов (например, других вкладок, других программ). Сон, напротив, временно приостанавливает использование потоком системных ресурсов.
ramcdougal
1
лучше использовать Date.now () вместо new Date () и не думать об утечках памяти
WayFarer
1
Конечно, это сильно загружает процессор, но для быстрого и грязного тестирования это работает
Maris B.
Мне нужна его версия, которая не блокирует поток, поэтому я могу обновить DOM перед delayзагрузкой (чтобы ответить на этот вопрос ). Есть ли способ сделать это?
Ги Имамура
3
Более компактная процедура: задержка функции (мс) {var start_time = Date.now (); while (Date.now () - start_time <мс); }
Герцог
15

Вам нужно использовать setTimeout и передать ему функцию обратного вызова. Причина, по которой вы не можете использовать sleep в javascript, заключается в том, что вы заблокируете всю страницу от каких-либо действий в это время. Не хороший план. Используйте модель событий Javascript и будьте счастливы. Не борись с этим!

Патрик
источник
2
Тем не менее, это было бы полезно для тестирования. Как задержка отправки формы на несколько секунд, чтобы оценить изменения страницы до того, как будет сделан новый HTTP-запрос.
rushinge
1
Затем @rushinge устанавливает обратный вызов для отправки формы и отключает отправку формы по умолчанию
Populus
1
Плохая идея оставить ссылку как код ... так как теперь это не работает.
Эммет Аррис
1
Или вы знаете, я мог бы просто исправить это.
Патрик
14

Вы также можете использовать window.setInterval () для повторного запуска некоторого кода через регулярные промежутки времени.

rcoup
источник
2
setInterval () не следует использовать вместо этого следует использовать setTimeout
Пол
9
setTimeout()делает это один раз, setInterval()делает это несколько раз. Если вы хотите, чтобы ваш код запускался каждые 5 секунд, setInterval()это сделано для работы.
rcoup
11

Чтобы добавить более ранние комментарии, я хотел бы сказать следующее:

setTimeout()Функция в JavaScript не приостанавливает выполнение сценария на себе, а лишь говорит компилятору , чтобы выполнить код когда - нибудь в будущем.

В JavaScript нет функции, которая может приостановить выполнение. Тем не менее, вы можете написать свою собственную функцию, которая выполняет что-то вроде безусловного цикла, пока не будет достигнуто время, используя Date()функцию и добавляя нужный интервал времени.

Нараси
источник
11

Если вам нужно только проверить задержку, вы можете использовать это:

function delay(ms) {
   ms += new Date().getTime();
   while (new Date() < ms){}
}

И затем, если вы хотите задержать на 2 секунды, вы делаете:

delay(2000);

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

Кристоффер
источник
@ U2744 SNOWFLAKE Можете ли вы попытаться быть более точным в своем комментарии
Christoffer
1
Что ж, это занятая петля, которая разряжает батареи ноутбуков и других мобильных устройств и, вероятно, также препятствует тому, чтобы пользовательский интерфейс реагировал (или даже отображал).
Ry-
@ U2744SNOWFLAKE Имеет смысл. Обновили ответ, для чего я использовал эту функцию :)
Christoffer
2
Работает достаточно хорошо в разработке для быстрого и грязного (и временного) решения.
HumanInDisguise
5

почему вы не можете поставить код за обещание? (напечатано на макушке)

new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000);
}).then(function() {
  console.log('do whatever you wanted to hold off on');
});

Аль Йослин
источник
5

Простой ответ:

setTimeout(
    function () {
        x = 1;
    }, 1000);

Вышеприведенная функция ждет 1 секунду (1000 мс), затем устанавливает x в 1. Очевидно, это пример; Вы можете делать все что угодно внутри анонимной функции.

Лука
источник
4

Мне очень понравилось объяснение Мауриуса (самый высокий отклик) с тремя различными методами вызова setTimeout.

В моем коде я хочу автоматически переходить на предыдущую страницу после завершения события сохранения AJAX. Завершение события сохранения имеет небольшую анимацию в CSS, указывающую на успешное сохранение.

В моем коде я обнаружил разницу между первыми двумя примерами:

setTimeout(window.history.back(), 3000);

Этот не ждет тайм-аута - функция back () вызывается почти сразу, независимо от того, какой номер я вставил для задержки.

Однако, изменив это на:

setTimeout(function() {window.history.back()}, 3000);

Это именно то, что я надеялся.

Это не относится к операции back (), то же самое происходит с alert(). В основном с alert()использованием в первом случае время задержки игнорируется. Когда я закрываю всплывающее окно, анимация для CSS продолжается.

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

Doug
источник
1

У меня было несколько команд ajax, которые я хотел запустить с задержкой между ними. Вот простой пример того, как это сделать. Я готов быть разорванным в клочья, хотя для моего нетрадиционного подхода. :)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

Вы можете скопировать блок кода и вставить его в окно консоли и увидеть что-то вроде:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076
JohnnyIV
источник
1

Самое простое решение для вызова вашей функции с задержкой:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}
Jackkobec
источник
0

функция задержки:

/**
 * delay or pause for some time
 * @param {number} t - time (ms)
 * @return {Promise<*>}
 */
const delay = async t => new Promise(resolve => setTimeout(resolve, t));

использование внутри asyncфункции:

await delay(1000);
Зухайр Таха
источник
-1

Как уже говорилось, setTimeout - ваша
самая безопасная ставка. Но иногда вы не можете отделить логику от новой функции, тогда вы можете использовать Date.now (), чтобы получить миллисекунды и сделать задержку самостоятельно ....

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

JavaSheriff
источник