繁体   English   中英

递归 function vs setInterval vs setTimeout javascript

[英]recursive function vs setInterval vs setTimeout javascript

我正在使用 NodeJs,需要调用无限 function,但我不知道什么是最佳性能的最佳选择。

递归 function

function test(){
//my code
test();
}

设置间隔

setInterval(function(){
//my code
},60);

设置超时

function test(){
//my code
setTimeout(test,60);
}

我想要在不崩溃服务器的情况下获得最佳性能。 我的代码有几个算术运算。

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

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

基本上在JS中就像应该处理的函数列表。 当你调用setTimeoutsetIntervalprocess.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,......

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

祝你的递归好运:-)

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

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

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

不知道你想要完成什么,但这是一种使用递归的“安全”方式... https://stackoverflow.com/questions/24208676/how-to-use-recursion-in-javascript/24208677

/*
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

假设Jan Juna描述的“性能延迟”,我尝试了这个简单的脚本来检查吞吐量方面是否存在任何差异:

间隔:

const max = 50;
const timer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500];

function crono(timer) {
  return new Promise(resolve => {
    const exit = [];
    let i = 0
    setInterval(() => i++, timer);

    setInterval(() => {
      exit.push(i);
      i = 0;
      if (exit.length === max) {
        const sum = exit.reduce((a, b) => (a + b), 0);
        const avg = sum / exit.length;
        console.log(`${timer} = ${avg}`);
        resolve(avg)
      }
    }, 1000);
  });
}

Promise.all(timer.map(crono)).then(process.exit);

超时:

const max = 50;
const timer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500];

function crono(timer) {
  return new Promise(resolve => {
    const exit = [];
    let i = 0

    const redo = () => {
      i++
      setTimeout(redo, timer);
    }

    setInterval(() => {
      exit.push(i);
      i = 0;
      if (exit.length === max) {
        const sum = exit.reduce((a, b) => (a + b), 0);
        const avg = sum / exit.length;
        console.log(`${timer} = ${avg}`);
        resolve(x)
      }
    }, 1000);

    redo();
  });
}

Promise.all(timer.map(crono)).then(process.exit);

这是输出vith nodejs 8.11:在吞吐量方面没有显示差异:

结果

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

您显示的setIntervalsetTimeout方式是相同的,只是setInterval更清晰。

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

递归setTimeout保证执行之间的延迟, setInterval - 没有。

让我们比较两个代码片段。 第一个使用setInterval

let i = 1;
setInterval(function() {
  func(i);
}, 100);

第二个使用递归setTimeout

let i = 1;
setTimeout(function run() {
  func(i);
  setTimeout(run, 100);
}, 100);

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

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

这是正常的,因为func's执行所花费的时间“消耗”了一部分间隔。

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

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

在边缘情况下,如果函数总是执行的时间长于delay ms,那么调用将完全没有暂停。

递归setTimeout保证固定delay (此处为100ms)。

recursive function :无尽的递归函数导致堆栈溢出。

setTimeout代码在上一次回调执行后总是会有至少 60 毫秒的延迟(最终可能会更多,但绝不会更少)

setInterval将尝试每 60 毫秒执行一次回调,无论上次回调何时执行。

//使用setInterval函数

setInterval(function(){Property=value;},1000);

1000毫秒=1秒; 像style.width等属性;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM