Reputation: 12997
I need to add a delay of about 100 miliseconds to my Javascript code but I don't want to use the setTimeout
function of the window
object and I don't want to use a busy loop. Does anyone have any suggestions?
Upvotes: 96
Views: 414031
Reputation: 1
Solution for Google Apps Script users:
I couldn't get the setTimeout() function to work with Google Apps Script (just keep getting the error that the function is not defined) so I had to do something like this using the getTime() function and creating a reference time object and then an infinite loop that creates a separate time object every time it loops and checks if the value is greater than the reference time + the delay we need. I guess this way of doing it is not that precise down to the millisecond because there is looping and computational power/lag involved but for an approximate delay for something that is not a big deal weather 1 second is actually 1.013 or similar it will work.
const delay = 3000 // in ms
const date = new Date();
let time = date.getTime() + delay;
console.log('Start before delay.')
// Any code before the delay here
while(1){
const date2 = new Date(); // diffetent date object for comparison
let breaker = date2.getTime();
if (breaker>time){
console.log('Delayed message.')
break;
}
}
// Code after the delay here
Upvotes: 0
Reputation: 872
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
})()
Upvotes: 40
Reputation: 1
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
Upvotes: -13
Reputation: 509
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.
Upvotes: 17
Reputation: 564
Actually only setTimeout
is fine for that job and normally you cannot set exact delays with non determined methods as busy loops.
Upvotes: 4
Reputation: 95434
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;
}
}
}
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()
).
Upvotes: 155
Reputation: 882631
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.
Upvotes: 3