简体   繁体   English

为什么我的jQuery函数在IE 8中导致“Stack Overflow”错误?

[英]Why is my jQuery function causing a 'Stack Overflow' error in IE 8?

I have a simple function which causes a Stack Overflow error in IE 8. The problem does not appear to occur in any other browser although I have not testing IE 7 or 6. 我有一个简单的功能,在IE 8中导致堆栈溢出错误。虽然我没有测试IE 7或6,但在任何其他浏览器中似乎没有出现此问题。

The exact error is as follow:- 确切的错误如下: -

 SCRIPT28: Out of stack space 
 jquery.min.js, line 2 character 7498
 SCRIPT2343: Stack overflow at line: 2 

The function in question: 有问题的功能:

function switchImage(size, objid, prefix, fullimage){

    if(size !== 'full'){
        var image = prefix + size + '/' + size +'_' + fullimage;
    }
    else {
        var image = prefix + size + '/' + fullimage;
    }

    $('#' + objid).data('type', size)
        .append('<img id="preload" src="' + image + '" style="display:none;" />')
            .find('#preload').load(function(){
                $('#' + objid).find('img').attr('src', image);
                $(this).remove();
            });
}

To give an overview of the use case I will explain the purpose of this function: 为了概述用例,我将解释此函数的用途:

When a user resizes an image (using jqueryUI resize) the width/height is compared in another function. 当用户调整图像大小时(使用jqueryUI调整大小),在另一个函数中比较宽度/高度。

Once the image grows to be of a certain size this function is then called which as you can see, appends a hidden <img> element to the DOM with the 'src' attribute of a higher resolution version of the image (or lower if the image is being downsized by the user. 一旦图像增长到一定大小,然后调用此函数,如您所见,将隐藏的<img>元素附加到DOM,使用更高分辨率版本的图像的'src'属性(如果用户正在缩小图像尺寸。

Once it has been loaded the src attribute of the visible element is updated and the hidden element is removed. 加载后,可更新可见元素的src属性,并删除隐藏元素。

This proved excellent dynamic switching of images as the user resizes them keeping the image quality good throughout the process.... 这证明了图像的优异动态切换,因为用户调整了图像的大小,在整个过程中保持图像质量良好....

I just can't seem to work out what is causing the problem in IE 8. With this function removed no errors occur, and although the error is present, the function still works as it should (although resize performance is poor anyway in IE 8). 我似乎无法解决IE 8中导致问题的原因。删除此功能不会发生错误,虽然存在错误,但该功能仍然可以正常工作(尽管在IE 8中调整性能仍然很差) )。

Any help would be greatly appreciated. 任何帮助将不胜感激。

UPDATE: I seem to have solved the original issue by rewriting the function to the following:- 更新:我似乎通过将函数重写为以下内容解决了原始问题: -

function switchImage(size, objid, prefix, fullimage){

    var $el = $('#' + objid);

    if(size !== 'full'){
        var image = prefix + size + '/' + size +'_' + fullimage;
    }
    else {
        var image = prefix + size + '/' + fullimage;
    }

    $el.data('type', size);

    $('<img id="preload" src="' + image + '" style="display:none;" />')
        .appendTo($el)
            .one('load', function(){
                $('#' + objid).find('img').attr('src', image);
                    $(this).remove();
                });
}

As you can see, the only real difference is that I am using .appendTo() rather than .append() as well as using jQuery .one() method to ensure that the load event only occurs once. 正如您所看到的,唯一真正的区别是我使用.appendTo()而不是.append()以及使用jQuery .one()方法来确保loa​​d事件只发生一次。 Though since the element is removed directly afterwards I don't understand why this should make any difference. 虽然之后直接删除了元素,但我不明白为什么这会产生任何影响。

I really would be interested to see if anyone can shed any light on this so I can learn how to avoid such issues in the future. 我真的很想知道是否有人可以阐明这一点,以便我可以学习如何在将来避免这些问题。 Cheers. 干杯。

Your initial function would have run straight into an infinite loop if you didn't have $(this).remove() . 如果您没有$(this).remove()那么您的初始函数将直接进入无限循环。 Essentially what you were doing was setting the src attribute to all img tags, including the preload image itself. 基本上你正在做的是将src属性设置为所有 img标签,包括预加载图像本身。 (replace $(this).remove() with console.log('loaded') and watch it loop infinitely in Firebug) (用console.log('loaded')替换$(this).remove() console.log('loaded')并在Firebug中观察它无限循环)

I would guess that in IE8, once the attribute is set to the preload image as well, it invoked your 'load' event handler first before executing the next line which is $(this).remove() (explaining the stack overflow), while other browsers might have first finished executing the entire function first, thus removing the preload image, which prevented the infinite loop. 我猜想在IE8中,一旦属性设置为预加载图像,它执行下一行( $(this).remove() (解释堆栈溢出) 之前)先调用'load'事件处理程序,而其他浏览器可能首先完成了整个函数的执行,从而删除了预加载图像,从而阻止了无限循环。 (This is just a guess) (这只是猜测)

A monkey patch to the initial version would be to use .find('img:not(#preload)') instead of just .find('img') . 初始版本的猴子补丁将使用.find('img:not(#preload)')而不仅仅是.find('img')

Your patch also prevents the infinite loop because .one() ensures it to only run once. 您的补丁也会阻止无限循环,因为.one()确保它只运行一次。

But ultimately I would refactor the function to the following: 但最终我会将函数重构为以下内容:

function switchImage(size, objid, prefix, fullimage){

    var $el = $('#' + objid),
        $image = $el.find('img'),
        $preload = $('<img>');

    if(size !== 'full'){
        var image = prefix + size + '/' + size +'_' + fullimage;
    }
    else {
        var image = prefix + size + '/' + fullimage;
    }

    $el.data('type', size);

    $preload
        .on('load', function () {
            $image.attr('src', image);
        })
        .attr('src', image);
}

Also note that the preload image actually does not need to be explicitly appended to the DOM to serve your purpose. 另请注意,预加载图像实际上不需要显式附加到DOM以满足您的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM