Open In App

GFact | Why setTimeout callback doesn’t get called or work?

Last Updated : 03 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Every JavaScript Developer must have used setTimeout() method to execute some code after a particular interval of time (let’s say T milliseconds). But more often you might have come across the issue that nothing happens when the setTimeout is invoked, or the setTimeout goes into an infinite loop. In this edition of GFact, we will deep dive into this and understand what happens behind the scenes of setTimeout callback and why doesn’t it get called as expected.

What is setTimeout() callback method?

The setTimeout() method sets a timer that executes a function or specified piece of code once the timer expires.

Consider the following code:

Javascript




<script>
    startTime = new Date().getTime();
    setTimeout(function gfgCallback() {
        endTime = new Date().getTime();
        alert(`This function is executed after ${Math.floor((endTime - startTime) / 1000)} seconds`);
    }, 3000);
</script>


In the above code, you’ll see that the code inside the callback function gets executed after 3 seconds. As a result, the alert is displayed after 3 seconds timeout, as expected.

Screenshot-from-2023-10-03-09-07-07

What is setTimeout() callback method?

What is setTimeout callback not getting called issue?

Consider the below code.

  • In this code as well, we are trying to setTimeout for 3 seconds, which should raise an alert as soon as timeout is done after 3 seconds.
  • Now after the timeout is done, we are doing some operation (lets say empty loop) for some time, as shown in the code.

Javascript




<script>
    startTime = new Date().getTime();
    setTimeout(function gfgCallback() {
        endTime = new Date().getTime();
        alert(`This function is executed after ${Math.floor((endTime - startTime) / 1000)} seconds`);
    }, 3000);
     
    // The below code is to simulate the execution
    // of millions of lines of code which blocks the
    // Call Stack of a large period of time
    while(new Date().getTime() - startTime < 9000) {
        // Do nothing
    }
</script>


Expected Output:

Screenshot-from-2023-10-03-09-07-07

Actual Output:

Screenshot-from-2023-10-03-09-12-55

Why doesn’t setTimeout() callback not get called after 3 seconds as mentioned in the code?

The setTimeout() method guarantees the execution of a callback function after atleast T milliseconds and after T milliseconds are over, its execution depends on the Call Stack of JavaScript Engine. It might happen that the execution is delayed for a much longer period of time as compared to T milliseconds as it will only start after the Call Stack becomes empty.

As a result, If there is any Execution Context inside the Call Stack, the Callback function will wait for the Call Stack to become empty, before doing the Timeout.

Let us debug this setTimeout Callback not getting called issue step by step

In the above code, you’ll observe that the callback function gfgCallback() gets executed after 9 seconds even when we have set the timer for 3 seconds only.

This happens because the Call Stack was occupied with the Global Execution Context for 9 seconds. The while loop was just to simulate the execution of millions of lines of code. We can see similar behavior while executing a large program which takes a large amount of time to execute.

Now, let’s further explore how JavaScript is executed in the background and what exactly is happening in the above code.

  • As soon as the execution of the JavaScript code starts, a Global Execution Context is pushed into the Call Stack.

setTimeout_1

  • The JavaScript Engine starts execution of the Global Execution Context.
  • As soon as the JS Engine encounters the setTimeout() method, it registers a timer of 3000 milliseconds in the Web APIs environment which is offered by the Web Browser.

setTimeout_2

  • Now, the JS Engine starts executing the while loop which has to run continuously for 9000 milliseconds.
  • After 3000 milliseconds have passed, the timer of 3000 milliseconds expires and the callback function is pushed inside the Callback Queue.

setTimeout_3drawio

  • Now, this Callback function will not get pushed directly into the Call Stack and will wait for it to become empty which will happen after 9000 milliseconds (because of the while loop).

setTimeout_5

  • So, the Event Loop continuously checks the Call Stack and soon as it becomes empty, the Event Loop pops the gfgCallback() function from the Callback Queue and inserts it into the Call Stack.

setTimeout_4

  • Finally, the JS Engine will execute the code inside the gfgCallback() function.

Does setTimeout() guarantee the execution of the code inside the callback function gfgCallback() after exactly T milliseconds?

Unfortunately, the answer is No.

Since JavaScript is a synchronous, single threaded language, it has only one Call Stack and it is always advised that we should never try to block the main thread while executing our JS code.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads