【问题标题】:jQuery memory leak with repeated .ajax calls重复 .ajax 调用的 jQuery 内存泄漏
【发布时间】:2010-09-01 11:20:15
【问题描述】:

我正在使用以下在 Firefox 中泄漏内存的模式:

$(function() {

    (function() {

        var callee = arguments.callee;

        $.ajax({
            url: '...',
            success: function() { ... setTimeout(callee, 1000); },
            error: function() { ... setTimeout(callee, 1000); }
        });

    })();

});

即使成功/错误除了再次调用 setTimeout 什么都不做,内存泄漏仍然存在。我正在通过 Windows 任务管理器观察泄漏;如果页面保持打开状态,firefox.exe 的内存使用会慢慢上升。对于这段代码的最终版本,我只需要每分钟更新一次,但每秒一次会更快地显示内存泄漏!

(注意:这看起来与this question 的问题非常相似,但那里选择的答案似乎不适合 Firefox)

【问题讨论】:

  • 函数被调用者在做什么?你确定没有循环引用吗?
  • “被调用者”模式只是匿名函数中计时代码的一种方式。即使代码与上面一样裸露,仍然存在内存泄漏。
  • Paul Irish 出色的 Things I learned from the jquery source 视频中讨论了该模式 - 大约在 8 分钟左右观看
  • 我有同样的问题尝试使用队列。

标签: jquery firefox memory-leaks


【解决方案1】:

我能够重现问题并解决它:

$(function() 
{
    function checkStatus() 
    {
        $.ajax({
          url: '...',
          success: function() { ... setTimeout(checkStatus, 1000); },
          error: function() { ... setTimeout(checkStatus, 1000); }
        });

    }

    checkStatus();

});

每次调用匿名方法时,它都会创建一个变量并为其分配一个引用。如果有足够的时间,这将填满内存。

此解决方案只是传递相同的函数 ref,而不是在每次迭代时创建一个新函数。

【讨论】:

    【解决方案2】:

    也许值得尝试这样的事情?

    $(function() 
    {
        (function() 
        {
            var callee = arguments.callee;
            $.ajax(
            {
                url: '...',
                success: function() 
                {
                    ... 
                    setTimeout(function()
                    {
                        callee();
                    }, 1000);
                 },
                 error: function() 
                 {
                    ... 
                    setTimeout(function()
                    {
                        callee();
                    }, 1000);
                  }
            });   
        })();
    });
    

    除了将 calle 传递给 setTimeout 回调之外,还需要传递一个调用 calle 的匿名函数。

    【讨论】:

      【解决方案3】:

      尝试像这样将被调用者放在函数之外:

      var callee = arguments.callee;
      
      $(function() {
      
          (function() {
      
              $.ajax({
                  url: '...',
                  success: function() { ... setTimeout(callee, 1000); },
                  error: function() { ... setTimeout(callee, 1000); }
              });
      
          })();
      
      });
      

      所以内存只为“被调用者”分配一次,而不是每次执行函数时。

      【讨论】:

      • callee 必须在函数内部,因为它指的是函数本身
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 2014-02-18
      • 2012-10-25
      • 2023-04-08
      • 1970-01-01
      • 2012-04-24
      相关资源
      最近更新 更多