递归函数vs setInterval vs setTimeout javascript

J26*_*261 10 javascript recursion performance settimeout setinterval

我正在使用NodeJs并需要调用无限功能,但我不知道什么是最佳性能.

递归函数

function test(){
//my code
test();
}
Run Code Online (Sandbox Code Playgroud)

的setInterval

setInterval(function(){
//my code
},60);
Run Code Online (Sandbox Code Playgroud)

的setTimeout

function test(){
//my code
setTimeout(test,60);
}
Run Code Online (Sandbox Code Playgroud)

我想要最好的性能而不会崩溃服务器.我的代码有几个算术运算.

感谢任何优化javascript性能的建议.

Jan*_*ůna 16

小心..你的第一个代码会阻止JavaScript事件循环.

基本上在JS中就像应该处理的函数列表.当你打电话setTimeout,setInterval或者process.nextTick你将给这个列表添加给定的功能,当正确的时间到来时,它将被处理..

第一种情况下的代码永远不会停止,因此它永远不会让事件列表中的其他函数被处理.

第二个和第三个案例是好的...有一点点差别.

如果你的功能需要处理10毫秒,间隔将是你的60毫秒..

  • 具有setInterval的函数将在以下时间内处理:0-10,60-70,120-130 ......(所以它之间的调用只有50ms延迟)
  • 但是使用setTimeout它将是:
    • 如果你先调用func:0-10,70-80,140-150,210-220,......
    • 如果你先调用setTimeout:60-70,130-140,200-210,......

所以区别在于你的功能启动之间的延迟,这在一些基于区间的系统中很重要,比如游戏,拍卖,股票市场......等.

祝你的递归好运:-)

  • 这是最完整、最正确的答案,在我看来应该被接受为答案。谢谢! (2认同)
  • 我明白了,您正在谈论 cca 10ms 在函数内执行执行。但另一个值得注意的区别是:第一个示例 (setInterval) 不会立即执行,而是在 60 毫秒后执行。第二个示例 (setTimeout) 将在调用函数 test() 时立即执行,然后每 60 毫秒执行一次。 (2认同)

Qua*_*one 10

如前所述,无限递归函数会导致堆栈溢出.时间触发的回调将在具有清除堆栈的自己的上下文中执行.

setInterval对于通过递归进行更准确的定期调用很有用setTimeout,但是,有一个缺点:即使抛出了未捕获的异常,也会触发回调.这通常每60毫秒产生几个字节长的日志条目,每天产生1'440'000个条目.此外setInterval,重负载的回调最终可能会导致无响应的脚本甚至是漏洞系统.

如果没有捕获到任何异常,则setTimeout在从函数返回之前不会执行递归立即递归.它将保证从回调函数返回后的其他任务的时间范围,而与函数的执行时间无关.


cha*_*ele 7

不知道你想要完成什么,但这是一种使用递归的"安全"方式... /sf/ask/1694607351/

/*
this will obviously crash... and all recursion is at risk of running out of call stack and breaking your page...

function recursion(c){
    c = c || 0;
    console.log(c++);
    recursion(c);
}
recursion();

*/

// add a setTimeout to reset the call stack and it will run "forever" without breaking your page!
// use chrome's heap snapshot tool to prove it to yourself.  :)

function recursion(c){
    setTimeout(function(c){
        c = c || 0;
        console.log(c++);
        recursion(c);
    },0,c);
}

recursion();

// another approach is to use event handlers, but that ultimately uses more code and more resources
Run Code Online (Sandbox Code Playgroud)


sol*_*... 7

递归setTimeout保证执行之间的延迟,而setInterval\xe2\x80\x93 则不然。

\n\n

让\xe2\x80\x99s 比较两个代码片段。第一个使用setInterval

\n\n
let i = 1;\nsetInterval(function() {\n  func(i);\n}, 100);\n
Run Code Online (Sandbox Code Playgroud)\n\n

第二个使用递归setTimeout

\n\n
let i = 1;\nsetTimeout(function run() {\n  func(i);\n  setTimeout(run, 100);\n}, 100);\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于setInterval内部调度程序将func(i)每 100 毫秒运行一次。

\n\n

func调用之间的实际延迟setInterval小于代码中的延迟!

\n\n

那\xe2\x80\x99是正常的,因为执行\xe2\x80\x9c所花费的时间消耗了func's\xe2\x80\x9d间隔的一部分。

\n\n

执行时间可能func's比我们预期的要长,并且需要超过 100 毫秒。

\n\n

在这种情况下,引擎等待func完成,然后检查调度程序,如果时间到了,则立即再次运行它。

\n\n

在边缘情况下,如果函数执行时间始终超过delay毫秒,则调用将完全不会暂停。

\n\n

递归setTimeout保证固定delay(这里是100ms)。

\n


Pau*_*per 0

递归函数会导致堆栈溢出。那不是你想要的。

setInterval您所展示的和方式setTimeout是相同的,只是setInterval更清晰。

我会推荐setInterval。(毕竟,这就是它的用途。)