2014-01-21 16 views
3

Возможно ли запустить этот «бесконечно», не вызывая переполнения стека или исчерпания памяти?Рекурсивный setTimeout в javascript

function eternal(){ 
    var time = recalculateTime(); 
    doSomething(); 
    setTimeout(eternal,time); 
} 

setTimeout(eternal,200000); 

Я не использую setInterval, потому что время запуска переменной.

+1

Ваш код должен работать нормально, так как он не исчерпывает память. У вас проблемы с этим? –

+0

Нет, это потому, что на другом языке, таком как C# или Java, что-то вроде этого в конечном итоге приведет к исключению переполнения стека, потому что это будет рекурсивный вызов. –

ответ

5

Это не рекурсивный вызов, потому что первый вызов eternal() фактически закончился до того, как setTimeout() называет следующий. Таким образом, это не техническая рекурсия и со временем не наращивает стек. Он может запускаться вечно без какого-либо наращивания, и это прекрасный способ сохранить что-то работающее снова и снова.

В ответ на один из ваших комментариев javascript не является многопоточным, поэтому он не создает несколько потоков для таймеров. Каждое событие таймера, которое срабатывает, просто помещает событие в очередь событий, и если в это время не запущено JS, это событие запускается (тем самым вызывая функцию обратного вызова). Если JS работает в то время, JS-движок ждет, пока выполняющийся в настоящее время JS не завершится, а затем будет обслуживать следующее событие в очереди событий (таким образом вызывая обратный вызов).

1

Все должно быть хорошо. После запуска setTimeout он вернется из функции eternal до того, как он снова вызовет его.

+0

Разве это не создаст каскад нитей, каждый ждет их детей, чтобы закончить? Просто интересно, я не очень хорошо знаком с асинхронной частью javascript. –

+1

Как я уже упоминал, и jfriend00 говорит в своем ответе, метод «вечный» заканчивается и возвращается до следующего вызова. Так что это не рекурсивно. –

Смежные вопросы