Reputation: 16450
As far as I understood from these two answers:
when setTimeout
is called recursively the stack should not grow but if you open a devtool in either FF or Chrome and run this function:
function recur(n = 10) {
console.trace();
console.log(n, '++++++++++++++++');
if (n > 0) setTimeout(() => recur(--n), 1000);
}
recur()
you'll see the following:
console.trace() debugger eval code:2:11
recur debugger eval code:2
<anonymous> debugger eval code:8
10 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
9 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
8 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
7 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
6 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
5 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
4 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
3 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
2 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
1 ++++++++++++++++ debugger eval code:3:11
console.trace() debugger eval code:2:11
recur debugger eval code:2
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
recur debugger eval code:4
(Async: setTimeout handler)
recur debugger eval code:4
<anonymous> debugger eval code:8
0 ++++++++++++++++
Why is that?
Upvotes: 3
Views: 517
Reputation: 8106
Asynchronous stack traces in Chrome Developer Tools... designed to keep you sane whilst trying to figure out why your function is in a setTimeout() recursion loop
The javascript thread model is the event loop. - https://flaviocopes.com/javascript-event-loop/
setTimeout()
isn't technically recursing. Its an asynchronous function call. Inside the thread, it returns a numeric id synchronously (you can call clearTimeout()
on it), then as a side effect adds your function to the end of the event-loop stack. Its a singlethreaded model, so once javascript has finished your current thread/event, it will pop the next function off the top of the stack for execution. Thus 1000ms is simply the minimum time for scheduled execution but it might take longer if it is still executing previous events/threads.
If I run this code in node, I get:
node
Welcome to Node.js v12.5.0.
Type ".help" for more information.
> function recur(n = 10) {
... console.trace();
... console.log(n, '++++++++++++++++');
... if (n > 0) setTimeout(() => recur(--n), 1000);
... }
undefined
>
> recur()
Trace
at recur (repl:2:11)
at repl:1:1
at Script.runInThisContext (vm.js:123:20)
at REPLServer.defaultEval (repl.js:384:29)
at bound (domain.js:415:14)
at REPLServer.runBound [as eval] (domain.js:428:12)
at REPLServer.onLine (repl.js:700:10)
at REPLServer.emit (events.js:205:15)
at REPLServer.EventEmitter.emit (domain.js:471:20)
at REPLServer.Interface._onLine (readline.js:314:10)
10 ++++++++++++++++
undefined
> Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
9 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
8 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
7 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
6 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
5 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
4 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
3 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
2 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
1 ++++++++++++++++
Trace
at recur (repl:2:11)
at Timeout._onTimeout (repl:4:31)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
0 ++++++++++++++++
Upvotes: 6