2012-05-17 17 views
6

Tengo una función simple que causa un error de desbordamiento de pila en IE 8. El problema no parece ocurrir en ningún otro navegador aunque no he probado IE 7 o 6.¿Por qué mi función jQuery causa un error de "desbordamiento de pila" en IE 8?

El error exacto es el siguiente: -

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

la función de que se trate:

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(); 
      }); 
} 

Para dar una visión general del caso de uso voy a explicar el propósito de esta función:

Cuando un usuario cambia el tamaño de una imagen (usando el tamaño de jqueryUI), el ancho/alto se compara en otra función.

Una vez que la imagen crezca, se llama a esta función que, como puede ver, agrega un elemento oculto <img> al DOM con el atributo 'src' de una versión de resolución superior (o inferior) si la imagen está siendo redujo por el usuario.

Una vez que se ha cargado el atributo src del elemento visible se actualiza y se retira el elemento oculto.

Esto resultó excelente conmutación dinámica de las imágenes como los redimensiona usuario manteniendo la calidad de imagen buena durante todo el proceso ....

Parece que no puedo averiguar qué está causando el problema en IE 8. Con esta función eliminada no se producen errores, y aunque el error está presente, la función sigue funcionando como debería (aunque el rendimiento de tamaño es pobre de todos modos en IE 8).

Cualquier ayuda sería muy apreciada.

ACTUALIZACIÓN: que parecen haber resuelto el problema original reescribiendo la función a lo siguiente: -

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(); 
       }); 
} 

Como se puede ver, la única diferencia real es que estoy usando .appendTo() en lugar de .append(), así como el uso del método jQuery .one() para garantizar que el evento de carga solo se produzca una vez. Sin embargo, dado que el elemento se elimina directamente después, no entiendo por qué esto debería marcar la diferencia.

Realmente me interesaría ver si alguien puede arrojar algo de luz sobre esto para que pueda aprender cómo evitar estos problemas en el futuro. Aclamaciones.

+0

¿Qué sucede cuando utiliza una versión no minimizada de jQuery? Al menos de esa manera obtendrá una referencia más significativa para el error. – RobG

+0

Pasa lo mismo ... Créalo o no cinco minutos después de publicar la pregunta ... Lo he resuelto. Pero no tengo idea de por qué ... actualizaré mi pregunta, ya que realmente me gustaría entender por qué esta ligera reescritura ha marcado la diferencia. – gordyr

+0

@gordyr ¿Puede darnos el código que llama a la función switchImage() para darme un contexto? –

Respuesta

3

Su función inicial se habría ejecutado directamente en un bucle infinito si no tenía $(this).remove(). Esencialmente, lo que estaba haciendo era configurar el atributo src en todas las etiquetasimg, incluida la imagen de precarga en sí. (Reemplace $(this).remove() con console.log('loaded') y verlo bucle infinito en Firebug)

yo supongo que en IE8, una vez que el atributo se establece en la imagen de precarga, así, se invoca el controlador de eventos 'carga' primera antes la ejecución de la La siguiente línea es $(this).remove() (que explica el desbordamiento de la pila), mientras que otros navegadores podrían haber terminado primero ejecutando la función completa, eliminando así la imagen de precarga, lo que impidió el bucle infinito.(Esto es solo una suposición)

Un parche de mono para la versión inicial sería usar .find('img:not(#preload)') en lugar de solo .find('img').

Su parche también previene el bucle infinito porque .one() garantiza que solo se ejecute una vez.

Pero en última instancia, me gustaría refactorizar la función a lo siguiente:

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); 
} 

También tenga en cuenta que la imagen de precarga en realidad no necesita ser añadido explícitamente a la DOM para servir a su propósito.

Cuestiones relacionadas