Что такое JavaScript-версия sleep ()?

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

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

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

1946
задан 12 revs, 10 users 38% 17 March 2018 в 18:15
поделиться

70 ответов

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>). [+1129]

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

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

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

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

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

1826
ответ дан Herohtar 17 March 2018 в 18:15
поделиться

Я использую многопоточный HTML5 Worker, который сможет прервать синхронный запрос XMLHttpRequest, указывающий на не отвечающий URL. Это не блокирует браузер.

https://gist.github.com/el-gringo/6990785

0
ответ дан user2882556 17 March 2018 в 18:15
поделиться

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

Sequencr.js

Превращает это:

setTimeout(function(timeout){
    function1();
    setTimeout(function(timeout){
        function2();
        setTimeout(function(timeout){
            function3();
        }, timeout, timeout)
    }, timeout, timeout)
}, 10, 10);

в это:

Sequencr.chain([function1, function2, function3], 10);

И имеет встроенную поддержку для петель что "спит" между каждой итерации.

1
ответ дан JSideris 17 March 2018 в 18:15
поделиться

Вы можете использовать закрывающий вызов setTimeout () с постепенно увеличивающимися значениями.

var items = ['item1', 'item2', 'item3'];

function functionToExecute(item) {
  console.log('function executed for item: ' + item);
}

$.each(items, function (index, item) {
  var timeoutValue = index * 2000;
  setTimeout(function() {
    console.log('waited ' + timeoutValue + ' milliseconds');
    functionToExecute(item);
  }, timeoutValue);
});

Результат:

waited 0 milliseconds
function executed for item: item1
waited 2000 milliseconds
function executed for item: item2
waited 4000 milliseconds
function executed for item: item3 
1
ответ дан tponthieux 17 March 2018 в 18:15
поделиться

Если вы хотите перевести анонимную функцию, например, созданную вами в качестве обработчика, я рекомендую следующее:

function()
{
if (!wait_condition)
    {
    setTimeout(arguments.callee, 100, /*comma-separated arguments here*/);
    }
//rest of function
}

Этот код говорит: «Если условие ожидания еще не выполнено, вызовите эта функция снова с этими аргументами. " Я использовал этот метод для передачи одних и тех же аргументов моим обработчикам, что фактически делает этот код незапрашивающим sleep () (который работает только в начале вашей функции).

1
ответ дан Aaron 17 March 2018 в 18:15
поделиться
var waitTillSomethingHappens = function(){  
    if(somethingHappened == 1)  
    {  
        alert('Something Happened get out of sleep');  
    }
    else
    {  
    setTimeout(waitTillSomethingHappens,1000);  
    }  
};
-5
ответ дан Dinu 17 March 2018 в 18:15
поделиться

  await new Promise(resolve => setTimeout(resolve, 2000));

убедитесь, что ваша вызывающая функция асинхронная

проверена и работает нормально

2
ответ дан ama527 17 March 2018 в 18:15
поделиться

В Livescript (который компилируется в Javascript) вы можете сделать следующее:

sleep = (ms, func) -> set-timeout func, ms

console.log "hello-1"
<- sleep 2000ms
console.log "hello-2"
<- sleep 2000ms
console.log "hello-3"
-2
ответ дан ceremcem 17 March 2018 в 18:15
поделиться

Функции JavaScript не допускают приостановки. С синхронными Javascript-процедурами реализованы. Процедуры ожидают операций ввода-вывода и времени ожидания. Доступно для JavaScript 1.7.

демо: демо сон демо приостановка процедуры

0
ответ дан Paul Stettler 17 March 2018 в 18:15
поделиться

Я предпочитаю эту функциональную функцию sleep:

const sleep = ms =>
    Promise(resolve => setTimeout(resolve, ms))
-1
ответ дан 2 revs, 2 users 88% 17 March 2018 в 18:15
поделиться

Это поможет вам.

var reloadAfter = 10; //seconds
var intervalId = setTimeout(function() {
    //code you want to execute after the time waiting
}, reloadAfter * 1000); // 60000 = 60 sec = 1 min
2
ответ дан 3 revs, 3 users 67% 17 March 2018 в 18:15
поделиться

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

. В этом примере генератор называть его собственным next(), поэтому, как только он уйдет, он сам по себе.

var h=a();
h.next().value.r=h; //that's how U run it, best I came up with

//sleep without breaking stack !!!
function *a(){
    var obj= {};

    console.log("going to sleep....2s")

    setTimeout(function(){obj.r.next();},2000)  
     yield obj;

    console.log("woke up");
    console.log("going to sleep no 2....2s")
    setTimeout(function(){obj.r.next();},2000)  
     yield obj;

     console.log("woke up");
    console.log("going to sleep no 3....2s")

     setTimeout(function(){obj.r.next();},2000) 
     yield obj;

    console.log("done");

}
1
ответ дан 2 revs 17 March 2018 в 18:15
поделиться

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

const { promisify } = require('util')
const sleep = promisify(setTimeout)

module.exports = () => {
  await someAsyncFunction()
  await sleep(2000)
  console.log('2 seconds later...')
}
-2
ответ дан 2 revs, 2 users 72% 17 March 2018 в 18:15
поделиться

Другой возможный способ:

var _timer;
clearTimeout(_timer);
_timer = setTimeout(function() {
    // Your code
}, 1000); // Delay for 1 s.
-1
ответ дан Aistis 17 March 2018 в 18:15
поделиться

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

0
ответ дан mukund 17 March 2018 в 18:15
поделиться

Я получил Promise - не конструктор, использующий верхний ответ. Если вы импортируете Bluebird, вы можете сделать это. Простейшее решение ИМО.

import * as Promise from 'bluebird';


  await Promise.delay(5000)
0
ответ дан ByteMe 17 March 2018 в 18:15
поделиться

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

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

setInterval (обратный вызов, время) будет долго ждать, а затем обратный вызов, в то время как блокировка времени выполнения. Текущая реализация "setInterval" далека от сохранения потока, даже не говоря уже о параллелизме.

Хотя упомянутые разреженные решения выглядят как, угадайте, что C # ( смеется ), они все еще не работают, как в C # / .NET. Они все еще работают как в C.

В настоящее время JavaScript НЕ предоставляет архитектуру для реализации реальной многопоточности. Лучшим подходом был бы TypeScript, но все же в нем так мало реального решения, что ... больно. JavaScript, JQuery, AJAX, JNode и даже TypeScript - это всего лишь группа Wannabes, полагающихся на благо и плохое настроение разработчиков. Факт. Полная остановка.

-6
ответ дан CarstenP 17 March 2018 в 18:15
поделиться

Если вы действительно хотите приостановить выполнение сценария, вы можете сделать это:

var milliseconds;
var pretime;
var stage;

function step(time){
  switch(stage){
    case 0:
      //Code before the pause

      pretime=time;
      milliseconds=XXX;
      stage=1;
      break;
    case 1:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=2;
      }
      break;
    case 2:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=3;
      }
      break;
    case 3:
      //Etc...
  }

  Window.requestAnimationFrame(step)
}

step();

Это, вероятно, именно то, что вы хотите, если вы все равно используете цикл, и вы можете изменить это таким образом, чтобы у вас была псевдо-многопоточность, когда некоторые функции ожидают некоторое время, а другие работают нормально. Я использую это все время для игр с чистым JS.

0
ответ дан Caty Lawren 17 March 2018 в 18:15
поделиться

Подводя итог (как было сказано в предыдущих ответах):

В JavaScript нет встроенной функции сна. Вы должны использовать setTimeout или setInterval для достижения аналогичного эффекта.

Если бы вы действительно хотели, вы могли бы смоделировать режим сна с помощью цикла for, подобного показанному в исходном вопросе, но это сделало бы ваш процессор сумасшедшим. Внутри Web Worker альтернативным решением было бы сделать синхронный XMLHttpRequest с неотвечающим IP и установить правильный таймаут. Это позволит избежать проблемы использования процессора. Вот пример кода:

// Works only inside a web worker

function sleep(milliseconds) {
	var req = new XMLHttpRequest();
	req.open("GET", "http://192.0.2.0/", false);
	req.timeout = milliseconds;
	try {
		req.send();
	} catch (ex) {
		
	}
}

console.log('Sleeping for 1 second...');
sleep(1000);
console.log('Slept!');

console.log('Sleeping for 5 seconds...')
sleep(5000);
console.log('Slept!');
0
ответ дан Miscreant 17 March 2018 в 18:15
поделиться

Я бы инкапсулировал setTimeOut в Promise для согласованности кода с другими асинхронными задачами: Демонстрация в Fiddle

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

Используется так:

sleep(2000).then(function() { 
   // Do something
});

Это синтаксис легко запомнить, если вы использовали Promises.

10
ответ дан Elo 17 March 2018 в 18:15
поделиться

На стороне сервера вы можете использовать метод deasync sleep(), который изначально реализован в C , поэтому он может эффективно реализовать эффект wait без блокирование цикла событий или загрузка процессора на 100%.

Пример:

#!/usr/bin/env node

// Requires `npm install --save deasync`
var sleep = require("deasync").sleep;

sleep(5000);

console.log ("Hello World!!");

Но если вам нужна javascript-функция pure (например, для запуска ее на стороне клиента через браузер), извините скажем, я думаю, что ваша функция pausecomp() - единственный способ приблизиться к ней, и, более того:

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

  2. Он загружает ваш процессор на 100%.

Итак, если вам это нужно для сценария браузера и вы не хотите этих ужасных эффектов, я должен сказать, что вы должны переосмыслить свою функцию таким образом:

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

[+1121] б). Или, если вам нужно дождаться результата, вам следует перейти к использованию обещаний (или, конечно же, к обратному вызову; -)).

Пример, ожидаемый результат:

function myFunc() {

    console.log ("Do some things");

    setTimeout(function doTheRest(){
        console.log ("Do more things...");
    }, 5000);

    // Returns undefined.
};


myFunc();

Пример возврата обещания (обратите внимание, что это меняет использование вашей функции):

function myFunc(someString) {

    return new Promise(function(resolve, reject) {

        var result = [someString];
        result.push("Do some things");

        setTimeout(function(){
            result.push("Do more things...");
            resolve(result.join("\n"));
        }, 5000);

    });

};


// But notice that this approach affect to the function usage...
// (It returns a promise, not actual data):
myFunc("Hello!!").then(function(data){
    console.log(data);
}).catch(function(err){
    console.error(err);
});
0
ответ дан 2 revs 17 March 2018 в 18:15
поделиться

Краткий ответ: НЕТ , но не в javascript. Похоже, что ваше решение - единственный способ не возвращать контроль обратно в окружающую среду.

Это необходимо, если среда не поддерживает события. Вероятно, они также не поддержали бы установленное время ожидания.

settimeout, безусловно, лучший способ, если вы находитесь в управляемой событиями среде, такой как браузер или node.js.

0
ответ дан Gerard ONeill 17 March 2018 в 18:15
поделиться

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

Во многих случаях можно использовать обещания (AJAX запрашивает общее использование). Они позволяют вам делать асинхронные вещи синхронно. Существует также обработка для успеха / неудачи, и они могут быть связаны.

Они являются частью ECMAScript 6, поэтому поддержка браузеров еще не все, в основном, IE не поддерживает их. Также есть библиотека Q для выполнения обещаний.

Ссылки: http://www.html5rocks.com/en/tutorials/es6/promises/

https://github.com/jakearchibald/es6- обещание # readme (Shim для старых или браузеров IE)

2
ответ дан 3 revs 17 March 2018 в 18:15
поделиться

У меня была похожая проблема: мне приходилось ждать существования контроля и проверять интервалы Поскольку в JavaScript нет реального сна, ожидания или паузы, а использование await / async не поддерживается должным образом в Internet Explorer, я принял решение, используя setTimeOut и ввод функции в случае успешного поиска элемента. Вот полный пример кода, так что каждый может воспроизвести и использовать его для своего собственного проекта:

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        var ElementSearchStatus = {
            None: 0,
            Found: 1,
            NotFound: 2,
            Timeout: 3
        };

        var maxTimeout = 5;
        var timeoutMiliseconds = 1000;

        function waitForElement(elementId, count, timeout, onSuccessFunction) {
            ++count;
            var elementSearchStatus = existsElement(elementId, count, timeout);
            if (elementSearchStatus == ElementSearchStatus.None) {
                window.setTimeout(waitForElement, timeoutMiliseconds, elementId, count, timeout, onSuccessFunction);
            }
            else {
                if (elementSearchStatus == ElementSearchStatus.Found) {
                    onSuccessFunction();
                }
            }
        }

        function existsElement(elementId, count, timeout) {
            var foundElements = $("#" + elementId);
            if (foundElements.length > 0 || count > timeout) {
                if (foundElements.length > 0) {
                    console.log(elementId + " found");
                    return ElementSearchStatus.Found;
                }
                else {
                    console.log("Search for " + elementId + " timed out after " + count + " tries.");
                    return ElementSearchStatus.Timeout;
                }
            }
            else {
                console.log("waiting for " + elementId + " after " + count + " of " + timeout);
                return ElementSearchStatus.None;
            }
        }

        function main() {
            waitForElement("StartButton", 0, maxTimeout, function () {
                console.log("found StartButton!");
                DoOtherStuff("StartButton2")
            });
        }

        function DoOtherStuff(elementId) {
            waitForElement(elementId, 0, maxTimeout, function () {
                console.log("found " + elementId);
                DoOtherStuff("StartButton3");
            });
        }
    </script>
</head>
<body>
    <button type="button" id="StartButton" onclick="main();">Start Test</button>
    <button type="button" id="StartButton2" onclick="alert('Hey ya Start Button 2');">Show alert</button>
</body>
</html>
0
ответ дан Franz Kiermaier 17 March 2018 в 18:15
поделиться

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

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

Эта функция создает новый контекст function () {}, чтобы избежать рекурсии. Мы поместили код, который делает то же самое, что и код вызывающей стороны, в этот новый контекст. Мы используем функцию Timeout для вызова нашей функции через несколько секунд.

var get_hyper = function (node , maxcount , only_relation) {
    if (node.offsetParent === null) {
            // node is hidden
            setTimeout(function () { get_hyper(node , maxcount , only_relation)}
                      ,1000);
            return;
    };

    // Enter here the code that wait that that the node is visible
    // before getting executed.

};
0
ответ дан MUY Belgium 17 March 2018 в 18:15
поделиться

Чтобы основной поток был занят в течение нескольких миллисекунд:

function wait(ms) {
  const start = performance.now();
  while(performance.now() - start < ms);
}
0
ответ дан pomber 17 March 2018 в 18:15
поделиться

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

// execute code consecutively with delays (blocking/non-blocking internally)
function timed_functions() 
{
this.myfuncs = [];
this.myfuncs_delays = []; // mirrors keys of myfuncs -- values stored are custom delays, or -1 for use default
this.myfuncs_count = 0; // increment by 1 whenever we add a function
this.myfuncs_prev   = -1; // previous index in array
this.myfuncs_cur    = 0; // current index in array
this.myfuncs_next  = 0; // next index in array
this.delay_cur     = 0; // current delay in ms
this.delay_default = 0; // default delay in ms
this.loop = false;      // will this object continue to execute when at end of myfuncs array?
this.finished = false;  // are we there yet?
this.blocking = true;   // wait till code completes before firing timer?
this.destroy = false;   // <advanced> destroy self when finished


this.next_cycle = function() {
var that  = this;
var mytimer = this.delay_default;

if(this.myfuncs_cur > -1)
if(this.myfuncs_delays[this.myfuncs_cur] > -1)
mytimer = this.myfuncs_delays[this.myfuncs_cur];

console.log("fnc:" + this.myfuncs_cur);
console.log("timer:" + mytimer);
console.log("custom delay:" + this.myfuncs_delays[this.myfuncs_cur]);
setTimeout(function() {
// times up! next cycle...
that.cycle(); 

}, mytimer);
}

this.cycle = function() {

// now check how far we are along our queue.. is this the last function?
if(this.myfuncs_next + 1 > this.myfuncs_count)
{
if(this.loop)
{
console.log('looping..');
this.myfuncs_next = 0;
}
else
this.finished = true;
}


// first check if object isn't finished
if(this.finished)
return false;

// HANDLE NON BLOCKING //
if(this.blocking != true) // blocking disabled
{
console.log("NOT BLOCKING");
this.next_cycle();
}


// set prev = current, and current to next, and next to new next
this.myfuncs_prev = this.myfuncs_cur;
this.myfuncs_cur  = this.myfuncs_next;
this.myfuncs_next++; 

// execute current slot
this.myfuncs[this.myfuncs_cur]();




// HANDLE BLOCKING
if(this.blocking == true)  // blocking enabled
{
console.log("BLOCKING");
this.next_cycle();
}




return true;
};

// adders 
this.add = {
that:this,

fnc: function(aFunction) { 
// add to the function array
var cur_key = this.that.myfuncs_count++;
this.that.myfuncs[cur_key] = aFunction;
// add to the delay reference array
this.that.myfuncs_delays[cur_key] = -1;
}
}; // end::this.add

// setters
this.set = {
that:this, 

delay:          function(ms)    {  
var cur_key = this.that.myfuncs_count - 1;
// this will handle the custom delay array this.that.myfunc_delays
// add a custom delay to your function container

console.log("setting custom delay. key: "+ cur_key + " msecs: " + ms);
if(cur_key > -1)
{ 
this.that.myfuncs_delays[cur_key] = ms; 
}

// so now we create an entry on the delay variable
},  

delay_cur:      function(ms)    { this.that.delay_cur = ms;         },
delay_default:  function(ms)    { this.that.delay_default = ms;         },
loop_on:          function()        { this.that.loop = true; }, 
loop_off:         function()        { this.that.loop = false; },
blocking_on:      function()        { this.that.blocking = true; }, 
blocking_off:     function()        { this.that.blocking = false; },

finished:           function(aBool) { this.that.finished = true; }
}; // end::this.set    


// setters
this.get = {
that:this, 

delay_default: function() { return this.that.delay_default; },
delay_cur:     function() { return this.that.delay_cur; }
}; // end::this.get     

} // end:::function timed_functions()

и использовать вроде: // // / / НАЧАЛО :: ТЕСТ // // //

// initialize
var fncTimer = new timed_functions;

// set some defaults
fncTimer.set.delay_default(1000);
fncTimer.set.blocking_on();
// fncTimer.set.loop_on();
// fncTimer.set.loop_off();


// BEGIN :: ADD FUNCTIONS (they will fire off in order)
fncTimer.add.fnc(function() {
    console.log('plan a (2 secs)');
});
fncTimer.set.delay(2000); // set custom delay for previously added function

fncTimer.add.fnc(function() {
    console.log('hello world (delay 3 seconds)');
});
fncTimer.set.delay(3000);

fncTimer.add.fnc(function() {
    console.log('wait 4 seconds...');
});
fncTimer.set.delay(4000);

fncTimer.add.fnc(function() {
    console.log('wait 2 seconds');
});
fncTimer.set.delay(2000);

fncTimer.add.fnc(function() {
    console.log('finished.');
});
// END :: ADD FUNCTIONS


// NOW RUN
fncTimer.cycle(); // begin execution 


// // // END :: TEST // // //
-1
ответ дан PlugTrade.com 17 March 2018 в 18:15
поделиться

Попробуйте эту простую функцию JavaScript:

function sleep(milliseconds) {
    var $return = false;
    if (typeof importScripts == 'function') {
        var sleep_xhr = function (milliseconds) {
            try {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', 'http://128.0.0.1:' + (Math.random() * 100000).toFixed(0) + '/', false);
                xhr.timeout = milliseconds;
                xhr.send();
            } catch (E) {
                // Nothing to do...
            }
        };
        milliseconds = milliseconds | 0;
        if (milliseconds > 0) {
            var start = Date.now();
            while (Date.now() < start + milliseconds) {
                sleep_xhr((start + milliseconds) - Date.now());
            }
            $return = Date.now() - start;
        }
    }
    return $return;
}

Примечание: эта функция работает только на веб-работников .

2
ответ дан Chandra Nakka 17 March 2018 в 18:15
поделиться

С поддержкой await и обещанием Bluebird :

await bluebird.delay(1000);

Это будет работать как синхронный sleep(1) языка c. Мое любимое решение.

2
ответ дан Guang-De Lin 17 March 2018 в 18:15
поделиться

Сначала:

Определите функцию, которую вы хотите выполнить следующим образом:

function alertWorld(){
  alert("Hello World");
}

Затем запланируйте ее выполнение с помощью метода setTimeout:

setTimeout(alertWorld,1000)

Обратите внимание на два Вещи

  • вторым аргументом является время в миллисекундах
  • . В качестве первого аргумента вы должны передать только имя (ссылку) функции без скобок
18
ответ дан Pablo Fernandez 17 March 2018 в 18:15
поделиться
Другие вопросы по тегам:

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