主要的JavaScript内存泄漏

时间:2011-04-08 14:30:26

标签: javascript jquery json memory-leaks closures

大家好!我正在开发某种事件日历,我正在使用jQuery作为前端,使用PHP作为后端。我有用PHP创建的所有日历数据并发送到客户端,JSON编码。

考虑以下代码(简化):

    jQuery(document).ready(function($) {

    // property which contains calendar object 
    this.Calendar; 
    // get calendar object 
    show_month();

    /* Assign a click event to the next month button */

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        show_month(month, year);
    });

    function show_month(month, year) {
        // delete pointers to the current month object
        window.Calendar = undefined;
        // get new month object
        window.Calendar = get_month(month, year);

        /* doing some stuff with this object here, like output to the 
           document etc., no event bindings */
    }

    function get_month(month, year) {
        var calendar;
        $.ajax({
            type: 'GET',
            dataType: 'json',
            async: false,
            timeout: 100,
            url: '../some_url.php?month='+month+'&year='+year,
            success: function(result) { calendar = result; }
        });
       return calendar;
    }

    var counter = 0;
    while (counter != 1000) {
        $('#cal_month .next span').trigger('click');
        counter ++;
    } 
});

手动切换月份以及制作循环会导致巨大的内存泄漏。我在这里和一般在互联网上阅读了一堆关于内存泄漏,js关闭等的信息,但我想我仍然有一些误解。我很高兴得到一些关于我的代码中出错的想法。

更新

我正在测量任务管理器中观看firefox.exe(其他浏览器遇到同样问题)的内存使用情况。即使我从页面导航,记忆也不会自由。经过一段时间后,它会导致性能下降,因为我可以使用600+ Mb。

我也编写了一个循环来切换月份(上面添加了代码)。

更新2

我使用全局的原因是在我的事件日历中我还有周视图和日视图,所以我希望一个活动的月份对象可用于处理这两个视图的函数,并且只销毁它并获得新的一个用户切换月份。我的问题恰好是全局变量的用法。那个解决了,现在试图找出如何保持对象可用,直到用户明确切换月份...

BTW,我创建了一个仅用于基准测试目的的while循环,它与我的实际代码无关。

5 个答案:

答案 0 :(得分:4)

我很想知道为什么你认为存在内存泄漏问题。还有两个我认为与记忆无关的大问题,但也许更重要。

第一个问题是同步服务器调用。您应该主要从不使用同步调用,因为在请求正在进行时锁定浏览器。 编辑:在该循环中执行此操作1000次将锁定浏览器最多1000 * 100毫秒,这将导致一些用户体验问题。

其次是全局Calendar对象。除了依赖混乱的全局状态之外,你还无法做同样页面上有2个日历的简单事情。

以下代码解决了这两个问题。

jQuery(document).ready(function($) {

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        generate_calendar(month, year);
    });

    generate_calendar();

    function calendar_fetch_complete(result) {
        var calendar = result;

        /* doing some stuff with this object here, like output to the 
           document etc.*/
    }

    function generate_calendar(_month, _year) {
        var month = _month || (new Date().getMonth() + 1),
            year  = _year  || (new Date().getYear() + 1900);
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: '../some_url.php?month='+month+'&year='+year,
            success: calendar_fetch_complete
        });
    }

});

答案 1 :(得分:2)

我建议使用像http://www.dynatrace.com/en/这样的工具,他们有时会提供帮助。

从John Resig本人那里查看本文http://ejohn.org/blog/deep-tracing-of-internet-explorer/

尝试遵循firebug技巧: 我建议你再试一次。简单的萤火虫技巧。当您不在UI控件上使用/鼠标操作时,只需单击firebug的分析按钮即可。看看有多少函数和调用正在发生,看看有什么东西是ODD并且需要很长时间。它很好的简单技巧,但帮助解决像这样的问题... :)

http://getfirebug.com/logging

Understanding Firebug profiler output

答案 2 :(得分:1)

var counter = 0;
while (counter != 1000) {
    $('#cal_month .next span').trigger('click');
    counter ++;
} 

什么?根据此代码,您将触发多个span元素1000次,并为每个元素请求1000次同步JSON,这将重写单个全局变量。这不是记忆“泄漏”,它已经筋疲力尽。

我建议重构你的代码以包含异步请求并取出while循环。

答案 3 :(得分:0)

你说有内存泄漏,但你是如何确定的呢?

可能您只是在查看浏览器进程内存使用情况。无论浏览器对内存做什么都不一定与你在javascript中做的事情有关。可能是javascript引擎没有释放它认为会再次使用的内存空间 - 无论你当前是否正在使用它。

请找到合适的工具来分析这个和/或提供有关您认为存在内存泄漏的原因的更多信息。

答案 4 :(得分:0)

  

while(counter!= 1000){           $('#cal_month .next span')。触发器('click');           counter ++;       }

这看起来像是在为某些东西分配1000个触发器 - 你不能处理来自父对象的任何点击吗?