递归'setTimeout'函数调用最终会杀死JS引擎吗?

Rob*_*ert 13 javascript recursion settimeout

假设我每隔10秒就需要从服务器获取一些数据.我将有一个函数通过AJAX获取数据,然后调用setTimeout再次调用此函数:

function GetData(){
   $.ajax({
       url: "data.json",
       dataType: "json",
       success: function(data){
         // do somthing with the data

         setTimeout(GetData, 10000);
      },
      error: function(){
         setTimeout(GetData, 10000);
      }
   });
}
Run Code Online (Sandbox Code Playgroud)

如果有人让网页全天开放,它可能会有数千个递归函数调用.

我不想使用setInterval,因为它没有考虑网络延迟.如果网络繁忙并且处理请求需要15秒,我不想在获得AJAX超时之前再次询问它.

处理需要定期调用的函数的最佳方法是什么?

lau*_*ent 24

没有实际的递归,因为在此期间对GetData的调用被延迟并且JavaScript上下文被销毁.所以它不会崩溃JS引擎.

对于您的代码示例,这基本上是JS引擎级别会发生的事情:

  1. 初始化JS引擎
  2. 创建GetData函数上下文
  3. 执行包含"setTimeOut"的GetData语句
  4. "setTimeOut"指示JS引擎在10秒内调用一个函数
  5. 销毁GetData函数上下文
  6. 此时,就内存使用而言,我们又回到了第1步.唯一的区别是JS引擎存储了对函数的引用以及何时调用它(让我们调用这个数据"futureCall").
  7. 10秒后,从步骤2开始重复."futureCall"被销毁.

  • @this.lau_ 如果 GetData 正在接受参数并且在调用 setTimeout 时将本地参数传递给它,会发生什么(就调用堆栈而言,而不是最终的内存不足错误)?例如像这样的要点:https://gist.github.com/anonymous/1769420ad62c1d5d9d82 由于被调用的函数引用了父函数的局部变量,所以它不需要维护调用堆栈吗? (4认同)
  • 规范中有一条注释说“永远不要破坏调用 setTimeout 的上下文”。这不是递归,因此任何实现都没有理由失败,即使是编码错误的实现。 (2认同)