I have a code which needs to be executed after some delay say 5000 ms.Currently I am using setTimeout but it is asynchronous and i want the execution to wait for its return.
Variation on the accepted answer which is just as good as this one.
Also, I agree with the caveats of preferring setTimeout
and asynchronous function calling but sometimes e.g., when building tests, you just need a synchronous wait command...
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
if you want it in seconds, divide start ms by 1000 on the while check...
const syncWait = ms => {
const end = Date.now() + ms
while (Date.now() < end) continue
}
Usage:
console.log('one')
syncWait(5000)
console.log('two')
const asyncWait = ms => new Promise(resolve => setTimeout(resolve, ms))
Usage:
(async () => {
console.log('one')
await asyncWait(5000)
console.log('two')
})()
const delayedCall = (array, ms) =>
array.forEach((func, index) => setTimeout(func, index * ms))
Usage:
delayedCall([
() => console.log('one'),
() => console.log('two'),
() => console.log('three'),
], 5000)
Non-timeout loops (that check the time or count to 1000000 or whatever) just lock up the browser. setTimeout
(or the $.doTimeout
plugin) is the best way to do it.
Creating timeouts within a loop won't work because the loop doesn't wait for the previous timeout to occur before continuing, as you've discovered. Try something more like this:
// Generic function to execute a callback a given number
// of times with a given delay between each execution
function timeoutLoop(fn, reps, delay) {
if (reps > 0)
setTimeout(function() {
fn();
timeoutLoop(fn, reps-1, delay);
}, delay);
}
// pass your function as callback
timeoutLoop(function() { alert("Hi"); },
5,
5000);
(I just cobbled this together quickly, so although I'm confident that it works it could be improved in several ways, e.g., within the "loop" it could pass an index value into the callback function so that your own code knows which iteration it is up to. But hopefully it will get you started.)
Solution using function generators. To show that it can be done. Not recommended.
function wait(miliseconds){
const gen = function * (){
const end = Date.now() + miliseconds;
while(Date.now() < end){yield};
return;
}
const iter = gen();
while(iter.next().done === false);
}
console.log("done 0");
wait(1000);
console.log("done 1");
wait(2000);
console.log("done 2");