Set Time Out in JavaScript

setInterval' vs 'setTimeout'

setTimeout(expression, timeout); runs the code/function once after the timeout.

setInterval(expression, timeout); runs the code/function repeatedly, with the length of the timeout between each repeat.

Example:

var intervalID = setInterval(alert, 1000); // Will alert every second.
// clearInterval(intervalID); // Will clear the timer.

setTimeout(alert, 1000); // Will alert once, after a second.

setTimeout in JS

The main confusion you are having is pretty common and comes from the fact that you are using a loop. Everything outside of the timer callback is JavaScript that is being executed synchronously with no delay. The loop executes 5 times immediately when you run the code and so 5 instances of the timer callback function get placed on the event queue in a matter of milliseconds and it is from that point in time that all 5 timer callbacks are delayed, rather than one callback being delayed from the completion of the prior one.

The first instance of the callback then runs after its initial delay is reached (1 second), then the second instance runs after its delay (2 seconds, which is only 1 second later than when the first function call ran) and then the third one runs (which is only 1 second behind the previous one of 2 seconds) and so on.

What you need to do is place the first instance of the callback on the event queue with a 1 second delay before it runs and then, when that first instance has completed, place another instance on the event queue with a 2 second delay, and so on.

To do this, forget the loop and make the timer function recursive, which will essentially cause a repeating code call, just as a loop would.

let delay = 1000;
let timer = null; // Will hold a reference to the timer

function x() {
timer = setTimeout(function(){
console.log(delay / 1000);
delay += 1000;
if(delay > 5000){
clearTimeout(timer); // Cancel the timer
console.log("Operation Complete!");
} else {
// Because the next call for the parent function comes from within
// the timer callback function, it is delayed until the end of that
// callback function's execution.
x();
}
}, delay);
}
x();

setTimeout function not working with for loop

I got it working with this:
(Thanks Yotam Salmon for your answer, thats what helped me understand what I was doing wrong)

I basically got each function to set the timeout and run the following one, then i got the last one to run the first one again. all i needed then was to start the first one manually then it just ran forever.

function slide1to2(){    document.getElementById('slide1').className = "hidden";    setTimeout(slide2to3, 4000);}function slide2to3(){    document.getElementById('slide2').className = "hidden";    setTimeout(slide3to1, 4000);}function slide3to1(){    document.getElementById('slide1').className = "";    document.getElementById('slide2').className = "";    setTimeout(slide1to2, 4000);}
slide1to2();
div#slideshow{ width:100%; height:50%; background-image:url("white-wall.png");}
div#slideshow div{ width:100%; height:inherit; background-repeat:no-repeat; background-position:center; background-color:rgba(0,0,0,0.5); position:absolute; transition:1s;}
div#slideshow div[id$="1"]{ background:#FF8888; transform:translateX(0%); z-index:3;}
div#slideshow div[id$="2"]{ background:#88FF88; transform:translateX(0%); z-index:2;}
div#slideshow div[id$="3"]{ background:#8888FF; transform:translateX(0%); z-index:1;}
div#slideshow div[id$="1"].hidden{ transform:translateX(-100%);}
div#slideshow div[id$="2"].hidden{ transform:translateX(-100%);}
<div id="slideshow">    <div id="slide1"></div>    <div id="slide2"></div>    <div id="slide3"></div></div>

setTimeout executes after for loop in javascript

JS is sync. So all sync code is done first, and all async go in separate thread and they may finish earlier but they have to wait until all sync code is done.

setTimeout(function(){
console.log('setTimeout executes');
},1000); // this function go async in separate thread
for(var i=0;i<10000;i++){
console.log('inside for loop'); // sync
}
console.log('after For Loop'); // sync
// after all sync code async result will be called
// console.log('setTimeout executes'); will happen here

If you want full picture of how JS engines works read this. It is very basic and helps a lot.

what is setTimeOut() function in javascript?

Not sure you what you want.

setTimeout is a method of the global window object. It executes the given function (or evaluates the given string) after the time given as second parameter passed.

Read more about setTimeout.

Why use setTimeout in deferred

The reason for doing this is to allow the javascript thread an opportunity to trigger any other events that may be waiting in the queue.

Javascript is single-threaded. If an event is triggered, it can only run when the currently running code has finished.

Using setTimeout with a zero time delay effectively tells the JS interpreter that the callback function call is part of a new context and that your current code block is finished. This means that JS will take the opportunity before calling callback() to check to see if any other events need to be handled.

Although this may delay callback() itself from being called immediately, this can be good for your site's overall performance:

Other events that may need to be handled include click events and other UI triggers. If you don't give them a chance to execute, it may make your user interface appear sluggish or non-responsive.

What is setTimeout doing when set to 0 milliseconds?

A few useful facts might help clarify what's happening:

  1. JavaScript is single-threaded. Asynchronous callbacks are assigned to a message placed in a message queue.
  2. When no code is currently executing, the event loop polls the message queue, requesting the next message in line to be processed (executed).
  3. setTimeout adds a message (with the callback provided) to the end of this queue after the specified delay has elapsed.

(Note: this means the delay in a setTimeout call is not a sure thing; it is the minimum delay before the callback is executed. The actual time taken depends on how long it takes to process any messages ahead of it in the queue.)

So what happens if the delay is set to 0? A new message is added to the queue immediately, and will be processed when the currently executing code is finished and any previously-added messages have been processed.

What's happening in your code

When you invoke setTimeout

setTimeout(function() { 
console.log('AAA');
}, 0);

…a message gets added to the queue with the specified callback. The rest of your code…

for (i = 0; i < 1000; i++) {
console.log('BBB');
}
// etc.

…continues executing synchronously. Once it has completely finished, the event loop polls the message queue for the next message and finds the one with your setTimeout callback, which is then processed (the callback is run).

The callback only ever gets executed after the currently executing code has finished, no matter how long that takes.

Further reading

For more details on the event loop, see:

  • Concurrency model and event loop—MDN
  • The JavaScript event loop: explained—Carbon Five

Why is setTimeout(fn, 0) sometimes useful?

In the question, there existed a race condition between:

  1. The browser's attempt to initialize the drop-down list, ready to have its selected index updated, and
  2. Your code to set the selected index

Your code was consistently winning this race and attempting to set drop-down selection before the browser was ready, meaning that the bug would appear.

This race existed because JavaScript has a single thread of execution that is shared with page rendering. In effect, running JavaScript blocks the updating of the DOM.

Your workaround was:

setTimeout(callback, 0)

Invoking setTimeout with a callback, and zero as the second argument will schedule the callback to be run asynchronously, after the shortest possible delay - which will be around 10ms when the tab has focus and the JavaScript thread of execution is not busy.

The OP's solution, therefore was to delay by about 10ms, the setting of the selected index. This gave the browser an opportunity to initialize the DOM, fixing the bug.

Every version of Internet Explorer exhibited quirky behaviors and this kind of workaround was necessary at times. Alternatively it might have been a genuine bug in the OP's codebase.


See Philip Roberts talk "What the heck is the event loop?" for more thorough explanation.

How to create your own setTimeout function?

Just for the game since I really don't see why you couldn't use setTimeout...


To create a non-blocking timer, without using the setTimeout/setInterval methods, you have only two ways:

  • event based timer
  • run your infinite loop in a second thread

Event based timer

One naive implementation would be to use the MessageEvent interface and polling until the time has been reached. But that's not really advice-able for long timeouts as this would force the event-loop to constantly poll new tasks, which is bad for trees.

function myTimer(cb, ms) {
const begin = performance.now();
const channel = myTimer.channel ??= new MessageChannel();
const controller = new AbortController();
channel.port1.addEventListener("message", (evt) => {
if(performance.now() - begin >= ms) {
controller.abort();
cb();
}
else if(evt.data === begin) channel.port2.postMessage(begin);
}, { signal: controller.signal });
channel.port1.start();
channel.port2.postMessage(begin);
}

myTimer(() => console.log("world"), 2000);
myTimer(() => console.log("hello"), 100);


Related Topics



Leave a reply



Submit