在 Javascript 中添加延迟

我需要添加一个大约100毫秒的延迟到我的 Javascript 代码,但我不想使用 window对象的 setTimeout函数,我不想使用一个繁忙的循环。有人有什么建议吗?

361487 次浏览

Unfortunately, setTimeout() is the only reliable way (not the only way, but the only reliable way) to pause the execution of the script without blocking the UI.

It's not that hard to use actually, instead of writing this:

var x = 1;


// Place mysterious code that blocks the thread for 100 ms.


x = x * 3 + 2;
var y = x / 2;

you use setTimeout() to rewrite it this way:

var x = 1;
var y = null; // To keep under proper scope


setTimeout(function() {
x = x * 3 + 2;
y = x / 2;
}, 100);

I understand that using setTimeout() involves more thought than a desirable sleep() function, but unfortunately the later doesn't exist. Many workarounds are there to try to implement such functions. Some using busy loops:

function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}

others using an XMLHttpRequest tied with a server script that sleeps for a amount of time before returning a result.

Unfortunately, those are workarounds and are likely to cause other problems (such as freezing browsers). It is recommended to simply stick with the recommended way, which is setTimeout()).

This thread has a good discussion and a useful solution:

function pause( iMilliseconds )
{
var sDialogScript = 'window.setTimeout( function () { window.close(); }, ' + iMilliseconds + ');';
window.showModalDialog('javascript:document.writeln ("<script>' + sDialogScript + '<' + '/script>")');
}

Unfortunately it appears that this doesn't work in some versions of IE, but the thread has many other worthy proposals if that proves to be a problem for you.

Actually only setTimeout is fine for that job and normally you cannot set exact delays with non determined methods as busy loops.

I just had an issue where I needed to solve this properly.

Via Ajax, a script gets X (0-10) messages. What I wanted to do: Add one message to the DOM every 10 Seconds.

the code I ended up with:

$.each(messages, function(idx, el){
window.setTimeout(function(){
doSomething(el);
},Math.floor(idx+1)*10000);
});

Basically, think of the timeouts as a "timeline" of your script.

This is what we WANT to code:

DoSomething();
WaitAndDoNothing(5000);
DoSomethingOther();
WaitAndDoNothing(5000);
DoEvenMore();

This is HOW WE NEED TO TELL IT TO THE JAVASCRIPT:

At Runtime 0    : DoSomething();
At Runtime 5000 : DoSomethingOther();
At Runtime 10000: DoEvenMore();

Hope this helps.

Use a AJAX function which will call a php page synchronously and then in that page you can put the php usleep() function which will act as a delay.

function delay(t){


var xmlhttp;


if (window.XMLHttpRequest)


{// code for IE7+, Firefox, Chrome, Opera, Safari


xmlhttp=new XMLHttpRequest();


}


else


{// code for IE6, IE5


xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");


}


xmlhttp.open("POST","http://www.hklabs.org/files/delay.php?time="+t,false);


//This will call the page named delay.php and the response will be sent to a division with ID as "response"


xmlhttp.send();


document.getElementById("response").innerHTML=xmlhttp.responseText;


}

http://www.hklabs.org/articles/put-delay-in-javascript

If you're okay with ES2017, await is good:

const DEF_DELAY = 1000;


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


await sleep(100);

Note that the await part needs to be in an async function:

//IIAFE (immediately invoked async function expression)
(async()=>{
//Do some stuff
await sleep(100);
//Do some more stuff
})()