JavaScript中的递归setTimeout

3
这段文本的意思是:是否可能无限运行该程序而不会导致堆栈溢出或内存耗尽?
function eternal(){
    var time = recalculateTime();
    doSomething();
    setTimeout(eternal,time);
}

setTimeout(eternal,200000);

我没有使用setInterval,因为触发时间是可变的。


1
你的代码应该可以正常运行而不会出现内存溢出的问题。你有困扰吗? - Peter Olson
不,这是因为在另一种语言,比如C#或Java中,类似这样的代码最终会产生堆栈溢出异常,因为它将是一个递归调用。 - Guillermo Gutiérrez
2个回答

6
这并不是一个递归调用,因为在setTimeout()调用下一次之前,第一次调用eternal()已经完成。因此,它在技术上不是递归调用,也不会随着时间的推移而增加堆栈。它可以无限运行,而不会导致任何积累,并且这是一个完美的方式来让某些东西不断地运行。
针对您的一个评论,javascript不支持多线程,因此不会为计时器创建多个线程。每个计时器事件都会将事件放入事件队列中,如果此时没有JS正在运行,则触发该事件(从而调用回调函数)。如果此时有JS正在运行,则JS引擎会等待当前执行的JS完成,然后服务于事件队列中的下一个事件(从而调用回调函数)。

1

没问题。一旦setTimeout运行,它会在再次调用之前从eternal函数中返回。


这样做会不会创建一系列线程,每个线程都在等待它们的子线程完成呢?只是好奇,我对JavaScript的异步部分不是很熟悉。 - Guillermo Gutiérrez
1
正如我所提到的,以及jfriend00在他的答案中所说的那样,“eternal”方法在下一次调用之前就会完成并返回。因此它实际上并不是递归的。 - Dave Zych

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接