如何在IE9上定期的AJAX请求期间避免内存泄漏

时间:2012-03-07 10:31:21

标签: javascript internet-explorer dom memory-management mootools

我开发了一个显示一些统计数据的网页 使用mootools 1.4.5,AJAX请求会定期刷新这些统计信息。

这是基本代码:

<script type="text/javascript">
   var statisticRequest = new Request.HTML({
      url: theURL,
      noCache: true,
      onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
         $(responseTree[0]).replaces($('statisticContainer'))
      }
   })

   function getCurrentStatistics() {
      statisticRequest.get()
   }

   window.addEvent('domready', function(){
      getCurrentStatistics.periodical(2000)
   });
</script>

在FF上一切正常,但IE9会不断分配内存,直到机器几乎冻结。 看起来垃圾收集器没有删除旧的DOM元素。

使用sIEve,我可以看到越来越多的DOM元素以及由此产生的内存使用量。

如何强制IE删除未使用的元素?

修改

如下所示使用destroy()会减慢内存消耗,但不会完全停止。删除Request.HTML没有进一步的效果。

<script type="text/javascript">
    var statisticRequest = new Request({
        url: theURL,
        noCache: true,
        onSuccess: function(responseText, responseXML) {
            var newStatistic = Elements.from(responseText)
            var oldStatistic = $('statisticContainer')
            newStatistic.replaces(oldStatistic)
            oldStatistic.destroy()
        }
    })

    function getCurrentStatistics() {
        statisticRequest.get()
    }

    window.addEvent('domready', function(){
        getCurrentStatistics.periodical(2000)
    });
</script>

2 个答案:

答案 0 :(得分:1)

是的,你可以。看看这个代码:

https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L743-747

它只会在dom中替换它。它不会在GC方面做太多 - 旧元素仍然存在 - 如果你想重新附加它。

http://jsfiddle.net/rE3JH/

var foo = document.id('foo');
new Element('div').replaces(foo);
console.log(foo); // still an element, though not in the dom

致电foo.destroy();以正确使用GC - 请参阅https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L802-807

或者,更新staticContainer的父级 - 将更改应用于innerHTML direct。另外,请记住.empty()dispose个子节点而不是destroy - 对于像你这样的期刊,你需要彻底,因为它可以随着时间的推移而雪崩。

答案 1 :(得分:-1)

我已经玩了一段时间了。我觉得你最好使用像mootools这样的东西。它经过了很好的测试,非常小。它还为您提供了许多额外的功能,这些功能都是跨浏览器兼容的,不需要进行扩展测试。

我运行以下代码超过两个小时没有内存泄漏。希望它能帮助提问者或其他人搜索堆栈溢出:首先是index.html文件:

        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
                <title>Untitled Document</title>
                <style>
                img.slide{
                    border:1px solid black;
                }
                </style>
                <script type="text/javascript" src="mootools/mootoolsCore.js">
                </script>
                <script type="text/javascript" src="mootools/mootoolsMore.js">
                </script>
                <script type="text/javascript">

        function data(){
            this.who="alan";
            this.pageHolder=1;
            this.lastPage = 4;
            this.count = 0;
        }

        var newData = new data();

        function changePage(newData,dirn){
            newData.dirn = dirn;
            saveData(newData);
        }

        function saveData(newData) {
            //alert("reached save data");
            var dataJSON = JSON.encode (newData);
            var request = new Request.JSON({
                method: 'post',
                url: 'forwardDataJson.php',
                data: {
                    json: dataJSON
                    },
                onComplete: function(jsonObj) {
                    newData.pageHolder = jsonObj.pageHolder;
                    newData.count = jsonObj.count;
                    $("picHolder").set('html','<img class="slide" src ="OpeningSlide/Slide'+jsonObj.pageHolder+'.jpg"/>');
                    $("alertBox").set('html',jsonObj.alertGiven);
                    $("countme").set('html',jsonObj.count);

                }
            }).send();
        };
        function getCurrentStatistics() {
              saveData(newData);
           }

           window.addEvent('domready', function(){
              getCurrentStatistics.periodical(2000)
           });

        </script>
            </head>
            <body>
                <div id="alertBox"></div>
                <button  type="button" onmousedown="changePage(newData,'backward')"/>backward</button>
                <button  type="button" onmousedown="changePage(newData,'forward')">forward</button>

                <div id="picHolder"><img class="slide" src ="OpeningSlide/Slide1.jpg"/></div>
                <div id="countme">0</div>

            </body>
        </html>

这会查找一系列图像(Slide1.jpg,Slid2.jpg等),然后在页面上显示它们。它每两秒检查一次新的信息并获得一个计数器号码。单击向前或向后使幻灯片每2秒运行一次。不是很令人兴奋,但它演示了使用AJAX和使用Mootools进行服务器调查的原则。

您还需要一个服务器端脚本。在这种情况下是:

        <?php
        if(get_magic_quotes_gpc()){
            $test = stripslashes($_POST['json']);
        }else{
            $test = $_POST['json'];
        }
        $obj = json_decode($test);

        $direction = $obj->{'dirn'};
        $counter = $obj->{'count'};
        ++$counter;
        $obj->{'count'} = $counter;
        switch ($direction) {
            case "forward":
                if($obj->{'pageHolder'} < $obj->{'lastPage'}){
                    ++$obj->{'pageHolder'} ;
                }
                break;
            case "backward":
                if($obj->{'pageHolder'} >1){
                    --$obj->{'pageHolder'} ;
                }
                break;

        }


        $reply = json_encode($obj);

        echo $reply;
        ?>

您会注意到我使用JSON将对象传入和传出服务器。这只是为了便于编码。如果你从来没有使用它(至少在我看来),因为一旦你了解它就可以直接使用它。

此示例应按原样运行。你只需要一个名为OpeningSlide的目录,它应该包含你的jpg幻灯片/图像,当然还有mootools libs。

希望这有帮助

如果你想知道PHP代码的前几行,那么它很容易解决JSON和魔术引号的问题。它可以调整服务器上打开或关闭的魔术引号。如果您知道服务器设置,可以将其删除。