Рекурсивный setTimeout заставляет стек расти - PullRequest
2 голосов
/ 08 апреля 2020

Насколько я понял из этих двух ответов:

, когда setTimeout вызывается рекурсивно, стек не должен расти, но если вы откроете devtool в FF или Chrome и запустите эту функцию:

function recur(n = 10) {
  console.trace();
  console.log(n, '++++++++++++++++');
  if (n > 0) setTimeout(() => recur(--n), 1000);
}

recur()

вы увидите следующее:

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 ++++++++++++++++

Почему это так?

1 Ответ

3 голосов
/ 08 апреля 2020

Асинхронные трассировки стека в Chrome Developer Tools ... разработаны, чтобы держать вас в здравом уме, пытаясь выяснить, почему ваша функция находится в рекурсии setTimeout () l oop

Модель потока javascript - это событие l oop. - https://flaviocopes.com/javascript-event-loop/

setTimeout() технически не рекурсивно. Это асинхронный вызов функции. Внутри потока он синхронно возвращает идентификатор нумерации c (для него можно вызвать clearTimeout()), а затем в качестве побочного эффекта добавляет вашу функцию в конец стека событий-l oop. Это однопоточная модель, поэтому, как только javascript завершит ваш текущий поток / событие, он выведет следующую функцию из верхней части стека для выполнения. Таким образом, 1000 мс просто минимальное время для запланированного выполнения, но это может занять больше времени, если он все еще выполняет предыдущие события / потоки.

Если я запускаю этот код в узле, я получаю:

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 ++++++++++++++++
...