Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the function called by setTimeout has no callstack limit?

timer =  window.setTimeout(function () {
    //do something
    window.setTimeout(arguments.callee, 1000);
}, 1000);

the result is that these codes work well.

but why doesn't it cause the error below?

Maximum Call Stack Size Exceeded

when debugging it, find the variable scope don't include the scope of previous executed "setTimeout function"

Who can explain this?

with documentation preferably.

like image 622
SKing7 Avatar asked Jul 08 '14 11:07

SKing7


People also ask

Is there a limit for setTimeout?

Maximum delay value Browsers including Internet Explorer, Chrome, Safari, and Firefox store the delay as a 32-bit signed integer internally. This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.

How many parameters does setTimeout accept?

Developers generally pass only two parameters to setTimeout method — the callback function and the timeout period.

Does setTimeout run multiple times?

The setTimeout() is executed only once. If you need repeated executions, use setInterval() instead. Use the clearTimeout() method to prevent the function from starting.

Can setTimeout cause stack overflow?

Set timeout would not cause stack overflow, because it is asynchronous. It will just put the callback to the event queue and not block the execution.


2 Answers

setTimeout is asynchronous (it returns before executing the callback), and the callback will be executed on a new, empty stack frame. That's the whole purpose. It will never overflow the stack.

It is not a recursive call, for which scope (in case of a non-tail-call-optimized function) would need to be retained. But that would also mean that the function became blocking, which is not what you want.

like image 53
Bergi Avatar answered Sep 27 '22 21:09

Bergi


This is because the Timeout callbacks are not stored in the stack as you are assuming: there are in a queue, waiting to be executed in its own stack. And in your code the queue is filled when the previous execution is completed, so the queue is not growing.

UPDATE: You can check the specs here, but I'm copying the text:

The setTimeout() method must run the following steps:

  1. Let handle be a user-agent-defined integer that is greater than zero that will identify the timeout to be set by this call.

  2. Add an entry to the list of active timeouts for handle.

  3. Get the timed task handle in the list of active timeouts, and let task be the result.

  4. Get the timeout, and let timeout be the result.

  5. If the currently running task is a task that was created by the setTimeout() method, and timeout is less than 4, then increase timeout to 4.

  6. Return handle, and then continue running this algorithm asynchronously.

  7. If the method context is a Window object, wait until the Document associated with the method context has been fully active for a further timeout milliseconds (not necessarily consecutively).

  8. Otherwise, if the method context is a WorkerUtils object, wait until timeout milliseconds have passed with the worker not suspended (not necessarily consecutively).

  9. Otherwise, act as described in the specification that defines that the WindowTimers interface is implemented by some other object.

  10. Wait until any invocations of this algorithm started before this one whose timeout is equal to or less than this one's have completed.

    Optionally, wait a further user-agent defined length of time.

like image 41
Pablo Lozano Avatar answered Sep 27 '22 21:09

Pablo Lozano