JavaScript: рекурсия settimeout бесконечное увеличение стека? - PullRequest
0 голосов
/ 30 января 2019

Моя цель - слайд-шоу фоновых изображений с HTML / CSS / JS.Многие решения, которые я нашел, продвигают что-то вроде этого:

my_recursion();

function my_recursion () {
 // cycle the Background image ...
 setTimeout(my_recursion, 3000);
}

Не ошибаюсь ли я, что это плохой стиль?Я ожидаю, что, например, в цикле 1000 все остальные 999 экземпляров my_recursion все еще открыты / в стеке?Разве это не создает бесконечный стек, который потребляет все больше и больше памяти?

Или есть какой-то интеллект, который делает что-то вроде "если функция вызывает себя в конце, (n-1) -йфункция уничтожена, включая все переменные, которые были назначены внутри нее "?

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Код в порядке.Он уничтожает все переменные, потому что при первом вызове.Это setTimeout() для следующего function и, наконец, возврата.Ваша функция не return следующая.

my_recursion();

function my_recursion () {
 // cycle the Background image ...
 setTimeout(my_recursion, 3000); //Sets timeout for next function.
 //returns undefined here
} 
0 голосов
/ 30 января 2019

В вашем вопросе ваша функция не имеет параметров.В реальной реализации, я надеюсь, вы планируете использовать их.

const cycleBackground = (elem, bgs = [], ms = 1e3, i = 0) =>
  ( elem.setAttribute ('style', bgs[i])
  , setTimeout
      ( cycleBackground      // function to schedule
      , ms                   // when to schedule, ms from now
      , elem                 // user-specified element to change
      , bgs                  // user-specified backgrounds
      , ms                   // user-specified delay
      , (i + 1) % bgs.length // next background index
      )
  )

const backgrounds =
  [ "background-color: red;"
  , "background-image: linear-gradient(45deg, cyan 0%, purple 75%);"
  , "background-color: green;"
  ]

// call site
cycleBackground
  ( document.body // element to target
  , backgrounds   // list of backgrounds
  , 3e3           // delay, 3 seconds
  )
p {
  text-align: center;
  font-size: 3vw;
  font-weight: bold;
  color: white;
}
<p>Wait 3 seconds...</p>
0 голосов
/ 30 января 2019

Это не приведет к бесконечному увеличению стека из-за того, что setTimeout работает, и, тем не менее, это не плохой стиль.

setTimeout не гарантирует, что код будет запущен непосредственно после заданного времени ожидания.Вместо этого по истечении этого времени он отправляет обратный вызов в «очередь», которая будет обрабатываться, когда стек пуст.Поэтому он будет работать только тогда, когда my_recursion вернется и стек пуст.

Если функция вызывает себя в конце (...)

my_recursionне называй себя никуда.Он просто передает себя в качестве аргумента setTimeout.После этого он просто продолжит выполнение, вернется сразу после него и будет извлечен из стека.

В этой презентации описываются стек и очередь событий.

...