1

I'm trying to understand the concept of setTimeout and I couldn't understand how it works. In the below example, when I gave the 1000 to the second setTimeout function I got the output as

1)Hello 567
2)Hello
3)Hello 123

But When I gave the setTimeout for all the functions as 0, it shows as

1)Hello 123
2)Hello 567
3)Hello

Initially, I assumed the innerfunction value is returned first then in the below case shouldn't be

1)Hello 567
2)Hello 123
3)Hello

Please help me understand

<!DOCTYPE html>
<html>

<body>

  <p>Click the button to wait 3 seconds, then alert "Hello".</p>

  <button onclick="myFunction()">Try it</button>

  <script>
    function myFunction() {
      setTimeout(function() {
        alert("Hello");
      }, 0, setTimeout(function() {
        alert("Hello 123");
      }, 0), setTimeout(function() {
        alert("Hello 567");
      }, 0));
    }
  </script>

</body>

</html>
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
Hema Nandagopal
  • 668
  • 12
  • 35
  • 1
    Your first `setTimeout` is not correctly closed... you provide it more than 2 arguments, which will be evaluated as arguments to pass to the callback. I don't think you intended that. – trincot Feb 18 '21 at 19:40
  • 4
    Do you know what the third (and fourth and so on) argument to [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) is used for? The output `Hello 123`, then `Hello 567`, then `Hello` makes sense, since the inner arguments need to be evaluated before the outer function call. This is always the case and is not specific to `setTimeout`. The only special thing about `setTimeout` is that a delay of `0` attempts to schedule function execution in the next event loop cycle. – Sebastian Simon Feb 18 '21 at 19:41

3 Answers3

4

Not sure whether this was intentional or a typo, but you're passing more than two arguments to the first setTimeout. I've deconstructed your code for clarity. This is what you're doing:


function hello () {
  alert("Hello");
}

function hello123 () {
  alert("Hello 123");
}

function hello567 () {
  alert("Hello 567");
}

setTimeout(hello, 0, setTimeout(hello123, 0), setTimeout(hello567, 0));

You're passing 4 arguments to the outer setTimeout call. The last two are evaluated first to resolve their values before being passed to (the outer/first) setTimeout.

setTimeout returns an ID, so if the inner calls return 555555 and 999999 respectively, this is the equivalent of:

setTimeout(hello, 0, 555555, 999999)

And because the inner calls get evaluated first you see those alerts first if they all have the same delay1.

If you increase the delay on the inner timeouts you'll see their alerts after, because the outer one expires first.


1. Due to the way timeouts are handled in the javascript event loop, it's possible that these could appear in a different order. I'm ignoring those idiosyncracies for the purposes of this discussion.

ray
  • 26,557
  • 5
  • 28
  • 27
1

I don't know what you're expecting by passing a third and fourth parameter to setTimeout, but it obviously evaluates before the root setTimeout.

To clarify, the 3rd and 4th parameters of the root setTimeout are the results of other setTimeout calls, so they need to be evaluated first before their results are passed the the root setTimeout.

Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • To clarify, the result of the second setTimeout (which is a timeout identifier), is needed for the root setTimeout as it's one of its parameters. //// Help me understand , this is where I got confused. Here the 3 rd alert should come as first & then second alert right? – Hema Nandagopal Feb 18 '21 at 19:45
  • I'm explaining the current behavior of your code which makes no sense. Could you explain what you are actually trying to achieve so I can make a better answer? – Guerric P Feb 18 '21 at 19:47
  • I'm trying to understand the concept of setTimeout in deeper :) – Hema Nandagopal Feb 18 '21 at 19:49
  • 1
    @HemaNandagopal _“Here the 3 rd alert should come as first & then second alert right?”_ — No, the timeout with `alert("Hello 123");` is evaluated _before_ the one with `alert("Hello 567");`. If you expect it to be the other way around and still use this confusing structure with nested functions, move the `)` after the second `0` to the end. – Sebastian Simon Feb 18 '21 at 19:49
  • @SebastianSimon I got it now. So when I gave 1000 to second setTimeout it was loading after 1st and 3rd because of the time and not because of the order of function execution right? – Hema Nandagopal Feb 18 '21 at 19:52
  • @HemaNandagopal you should take a look at the other answer because your problem might be related to a silly typo – Guerric P Feb 18 '21 at 19:52
  • @GuerricP , Yes I was trying to understand the concepts and that mistake which I made makes perfect sense. Thanks. – Hema Nandagopal Feb 18 '21 at 19:54
  • @HemaNandagopal As you can see from the documentation here https://www.w3schools.com/jsref/met_win_settimeout.asp, setTimeout only takes 2 parameters: the function to call and the number of MILLIseconds to wait. – raphael75 Feb 18 '21 at 19:58
  • @raphael75 this doc is actually incomplete, the following parameters are actually passed to the callback after the delay – Guerric P Feb 18 '21 at 19:59
  • 1
    @GuerricP That page does show that additional parameters can be passed a little farther down in the "Parameter Values" section. – raphael75 Feb 18 '21 at 20:06
  • @raphael75 The proper documentation link (to MDN, a reputable source) has already been linked above. – Sebastian Simon Feb 18 '21 at 20:11
1

You didn't close out the first setTimeout() call with ).

You can now see that they run in the sequence that they were invoked, which is the sequence that they are placed on the event queue.

<!DOCTYPE html>
<html>

<body>

  <p>Click the button to wait 3 seconds, then alert "Hello".</p>

  <button onclick="myFunction()">Try it</button>

  <script>
    function myFunction() {
      setTimeout(function() {
        alert("Hello 1");
      }, 0)
      , setTimeout(function() {
        alert("Hello 2");
      }, 0)
      , setTimeout(function() {
        alert("Hello 3");
      }, 0);
    }
  </script>

</body>

</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71