Что такое 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 ]

0 голосов
/ 01 сентября 2015

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

В 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 голосов
/ 19 сентября 2018

У меня была похожая проблема: мне пришлось ждать существования элемента управления и проверять его через определенные промежутки времени. Поскольку в 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 голосов
/ 19 декабря 2017

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

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

module.exports = () => {
  await someAsyncFunction()
  await sleep(2000)
  console.log('2 seconds later...')
}
0 голосов
/ 10 июля 2017

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

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

0 голосов
/ 12 марта 2014

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

// 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 // // //
0 голосов
/ 06 апреля 2016

В 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"
0 голосов
/ 23 марта 2016

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

var _timer;
clearTimeout(_timer);
_timer = setTimeout(function() {
    // Your code
}, 1000); // Delay for 1 s.
0 голосов
/ 15 февраля 2013

Или просто создайте это:

function yourFunction(){

   //do something
   setInterval(myFunc(),1000);
   //do something else

}

function myFunc(){
   return;
}

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

0 голосов
/ 31 октября 2013

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

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

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

0 голосов
/ 04 апреля 2017

У меня был этот вопрос в течение долгого времени, и мне нужен был не совсем тот ответ, который был здесь представлен. Эта функция ожидания вызывает синхронное ожидание, которое не связывает процессор. waitForIt отправляет ajax-запрос в любое место и устанавливает для флага асинхронности значение false. waitF делает то же самое с фреймом, а waitD делает то же самое с div. Ajax занимает около 100 мс, фрейм - около 25, а div - около 1. Функция ожидания использует все это в зависимости от того, сколько времени вы даете. Если это не заставило себя долго ждать, сделайте это снова. Мне это нужно при работе с несколькими асинхронными загрузочными элементами. В основном для «подождите, пока этот элемент существует». Вы можете поиграть с ним здесь https://jsfiddle.net/h2vm29ue/ Он просто использует то, что естественно ожидает браузер. Более длинная версия https://jsfiddle.net/5cov1p0z/32/ точнее.

 function waitForIt() {
     var start = new Date();
     var xhttp = new XMLHttpRequest();
     xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
            //doesn't matter
         }
     };
     xhttp.open("GET", "WaitForIt", false);
     xhttp.send();
     var end = new Date();
 }
 //



 function waitF() {
     var start = new Date();
     var ifram = document.createElement('iframe');
     ifram.id = 'ifram';
     ifram.src = '';
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     document.getElementById('timer').appendChild(ifram);
     document.getElementById('timer').removeChild(ifram);
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }


 function waitD() {
     var start = new Date();
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     div.click();
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }

 function wait(time) {
     var start = new Date();
     var end = new Date();
     while ((end - start < time)) {

         if ((time - (end - start)) >= 200) {
             waitForIt();
         } else {
             if ((time - (end - start)) >= 50) {
                 waitF();
             } else {
                 waitD();
             }

         }
         end = new Date();
     }
     return (end - start);
 }
...