有像Jquery内存或缓存的东西吗?

时间:2012-02-21 11:50:37

标签: javascript jquery caching memory

我用jQuery编写了一个用于360deg产品预览的脚本。它工作得很好。但如果我长时间“玩”它(拖动,放大,缩小等),它就会越来越慢。如果我慢慢地拖动鼠标它可以正常工作,但它会在快速鼠标移动时冻结。页面重新加载后,它会再次正常工作几分钟,然后变慢。

什么可能导致这种行为?是否有类似jQuery内存的内容会变满?

根据请求,代码的某些部分:

正在加载图片:

$.getJSON("load.php", {dir: 'images/'}, function(output) {
var imagelist = jQuery.makeArray(output.imagelist);
var zoomlist = jQuery.makeArray(output.zoomlist);
var cache = [];

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        var im = $("<img>").attr("src",this);
        cache.push(im);
        image.attr('src', this);
    });
}
preload(imagelist);

旋转部分

holder.mousedown(function(e){
    var enterPosition = e.pageX - this.offsetLeft;
    isDown = true;
    $(document).mousemove(function(e){
        if(isDown && !isZoom){
            var cursorPosition = e.pageX - contOffset.left;
            var xOffset = cursorPosition - enterPosition;
            var step = Math.round(contWidth/countFrames);
            var frameOffset = Math.round(xOffset/step);
            var cycles = Math.abs(Math.floor((frameOffset+startFrame)/countFrames));

            currentFrame = startFrame + frameOffset;
            if(currentFrame >= countFrames){
                currentFrame = currentFrame - countFrames*cycles;
            }       
            if(currentFrame < 0){
                currentFrame = countFrames*cycles + currentFrame;
            }

            image.attr('src', imagelist[currentFrame]);
            $('#info').html(currentFrame);      
            var corner = Math.floor(360/countFrames);                       
            var degrees = corner*currentFrame;                              
            var radians=degrees*Math.PI/180;
            var sine=Math.sin(radians);
            var cose=Math.cos(radians);
            var poinx = rotCenter+rotRadius*sine*-1;
            var poiny = rotCenter+rotRadius*cose
            $('#pointer').css('left',poinx);
            $('#pointer').css('top',poiny);
        };
    });
    $(document).mouseup(function(){
        isDown = false;
        startFrame = currentFrame;
    });
});

缩放部分

$('#zoom').click(function(e){
    var isZoom = true;

    var offset = holder.offset();
    var startXpos = e.pageX - offset.left;
    var startYpos = e.pageY - offset.top;
    var zoomImg = new Image();

    zoomImg.onload = function() {
        zoomHeight = zoomImg.height;
        zoomWidth = zoomImg.width;

        var leftOverflow = (zoomWidth - contWidth)/-2;
        var topOverflow = (zoomHeight - contHeight)/-2;

        image.attr('src', zoomlist[currentFrame]);
        image.css('left', leftOverflow);
        image.css('top', topOverflow);
        $('#round').fadeOut();
        $('#zoom').fadeOut();           
        holder.addClass('zoomout');
        holder.mousemove(function(e){
            if(isZoom){
                var currentXpos = e.pageX - offset.left;
                var currentYpos = e.pageY - offset.top;

                var xlimit = (zoomWidth-contWidth)*-1;
                var ylimit = (zoomHeight-contHeight)*-1;



                var xSpeedCoeff = Math.floor(zoomWidth/contWidth);
                var ySpeedCoeff = Math.floor(zoomHeight/contHeight);
                var moveLeft = startXpos - currentXpos;
                var moveTop = startYpos - currentYpos;
                var leftOffset = leftOverflow + moveLeft*xSpeedCoeff;
                var topOffset = topOverflow + moveTop*ySpeedCoeff;
                var hMoveLock = false;
                var vMoveLock = false;


                if(leftOffset >= 0){
                    hMoveLock = true;
                    startXpos = startXpos - leftOffset;
                } 
                if(leftOffset <= xlimit){
                    hMoveLock = true;
                    startXpos = startXpos - leftOffset + xlimit;    
                }

                if(topOffset >= 0){
                    vMoveLock = true;
                    startYpos = startYpos - topOffset;
                } 
                if(topOffset <= ylimit){
                    vMoveLock = true;
                    startYpos = startYpos - topOffset + ylimit; 
                }

                if(!hMoveLock) {
                    image.css('left', leftOffset);
                }
                if(!vMoveLock) {
                    image.css('top', topOffset);
                }

                holder.mousedown(function(){

                    image.attr('src', imagelist[currentFrame]);
                    image.css('left', 0);
                    image.css('top', 0);
                    $('#round').fadeIn();
                    $('#zoom').fadeIn();            
                    holder.removeClass('zoomout');
                    pan = false;
                    isZoom = false;
                });
            }
        });
    }
    zoomImg.src = zoomlist[currentFrame];
}); 

我知道,代码不清楚,就像现在这样,我会感谢任何建议。

3 个答案:

答案 0 :(得分:6)

有很多原因可能会发生这种情况,如果没有看到代码 ,现在您已发布代码 p>

我头脑中有几种可能性:

  1. 是的,您可以分配大量对象,然后不释放它们,或者垃圾收集器速度很慢。

  2. 您可能无意中反复重新附加事件处理程序,因此事件(最终会触发所有连接的处理程序)因为附加的(冗余)处理程序数量而减慢。

    < / LI>
    发布代码后

    更新

    这是#2,这是有问题的代码(可能不是违规代码):

    holder.mousedown(function(e){
        var enterPosition = e.pageX - this.offsetLeft;
        isDown = true;
        $(document).mousemove(function(e){
            // ...
        });
        $(document).mouseup(function(){
            // ...
        });
    });
    

    您正在执行的操作是mousedown事件触发holder事件时,您为{{1}添加新处理程序}和mousemove到文档,在已经存在的任何处理程序之上。所以每个mousedown都会为链引入一个新的处理程序。由于mouseup发生批次,因此不断增加的处理程序链称为批次

    您应该只附加mousemovemousemove处理程序一次,而不是每个mouseup,或者您应该确保删除他们在mousedown。 (后者要求你不要像现在这样使用匿名函数,因为你需要将相同的函数引用传递给你[间接]传递给{{1}的mouseup }}。编辑:或者您可以使用jQuery的“命名空间”事件。)


    FWIW,这应该让你开始使用attach-it-once版本:

    unbind

    如果您的代码已经在范围函数中,则不需要我引入的新代码。

答案 1 :(得分:1)

有一个缓存 - 您可以使用$.cache访问它。而作为T.J.克劳德说 - 这很可能是因为你没有正确地清理自己。

在控制台中执行Object.keys($.cache).length;以检查缓存的大小 - 播放一段时间并再次检查以确认缓存增长以确认基于jquery的泄漏

并且你在mouseup上泄漏原因你没有解开你的mouseup和mmousemove事件

$(document).mouseup(function(){
    $(document).unbind('mouseup').unbind('mousemove');
    isDown = false;
    startFrame = currentFrame;
});

这应该有很多帮助

问题是,基本上每当你按下鼠标时,你都会一次又一次地绑定鼠标和鼠标,所以点击几次后,所有的计算都乘以你按下鼠标的次数。您还可以将mousemove和mouseup事件命名为unname,而不是命名空间而不是两个事件。

同样缓存变量可能会有所帮助 - 特别是在这种繁重的操作时 - 鼠标移动很多

编辑:

使用匿名函数删除事件使用命名空间

var doc = $(document);

doc.bind('mousedown', function(e) {

    doc.bind('mousemove.namespace', function(e) { ... });

    doc.bind('mouseup.namespace', function(e) {

        doc.unbind('.namespace');

        // do whatever else you need to do on mouseup
    });
});

只需将名称空间更改为最适合您的名称!有关命名空间事件http://docs.jquery.com/Namespaced_Events

的更多信息,请查看jQuery文档

除此之外,如果你没有将任何函数传递给你想要取消绑定的事件类型,它将取消绑定给定类型的所有事件,无论其名称空间是什么,或者它是否被命名为函数或匿名函数

答案 2 :(得分:0)

因此,问题是由缩放功能引起的。我做了什么来解决它:

我已移动此部分

holder.mousedown(function(){
   image.attr('src', imagelist[currentFrame]);
   image.css('left', 0);
   image.css('top', 0);
   $('#round').fadeIn();
   $('#zoom').fadeIn();            
   holder.removeClass('zoomout');
   pan = false;
   isZoom = false;
});

以外的

holder.mousemove(function(e){
   if(isZoom){

我已经使用命名空间取消绑定鼠标事件。

holder.on('mousemove.dragpan', (function(e){
}));

holder.mousedown(function(){
   holder.off('mousemove.dragpan');
});

再次感谢所有的tipps!