2012-05-17 3 views
6

Ich habe eine einfache Funktion, die einen Stack Overflow-Fehler in IE 8 verursacht. Das Problem scheint nicht in einem anderen Browser auftreten, obwohl ich IE 7 oder 6 nicht testen.Warum verursacht meine jQuery-Funktion einen 'Stack Overflow'-Fehler in IE 8?

Der genaue Fehler ist wie folgt: -

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

die Funktion in Frage:

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

einen Überblick über den Anwendungsfall geben, werde ich den Zweck dieser Funktion erklären:

Wenn ein Benutzer die Größe eines Bildes ändert (mit jQueryUI resize), wird die Breite/Höhe in einer anderen Funktion verglichen.

Sobald das Bild eine bestimmte Größe hat, wird diese Funktion aufgerufen, die, wie Sie sehen können, ein verborgenes Element an das DOM mit dem Attribut 'src' einer höheren Auflösung des Bildes (oder niedriger) anfügt wenn das Bild durch die Benutzer verkleinerten wird.

Sobald es das Attribut src des sichtbaren Elements wird aktualisiert und das versteckte Element entfernt geladen wurde.

Diese ausgezeichnete dynamische Umschaltung von Bildern, wie der Benutzer komprimiert die Größe bewiesen Sie halten die Bildqualität während des gesamten Prozesses gut ....

Ich kann einfach nicht herausfinden, was das Problem in IE 8 verursacht. Mit dieser Funktion entfernt keine Fehler auftreten, und obwohl der Fehler vorhanden ist, funktioniert die Funktion immer noch wie es sollte (obwohl Größe Leistung im IE sowieso schlecht ist 8).

Jede Hilfe würde sehr geschätzt werden.

UPDATE: Ich scheine das ursprüngliche Problem gelöst zu haben, indem die Funktion der folgenden Umschreiben: -

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

Wie Sie sehen können, der einzige wirkliche Unterschied ist, dass ich .appendTo bin mit() anstelle von .append() sowie mithilfe der Methode jQuery .one(), um sicherzustellen, dass das Ladeereignis nur einmal auftritt. Obwohl das Element direkt danach entfernt wird, verstehe ich nicht, warum dies einen Unterschied machen sollte.

Ich wäre wirklich interessiert zu sehen, ob irgendjemand etwas Licht auf dieses Thema werfen kann, damit ich lernen kann, solche Probleme in der Zukunft zu vermeiden. Prost.

+0

Was passiert, wenn Sie eine nicht-reduzierte Version von jQuery verwenden? Auf diese Weise erhalten Sie eine aussagekräftigere Referenz für den Fehler. – RobG

+0

Das gleiche passiert ... glauben Sie es oder nicht fünf Minuten nach dem Posten der Frage ... Ich habe es gelöst. Aber ich habe keine Ahnung warum ... Ich werde meine Frage aktualisieren, da ich wirklich gerne verstehen würde, warum diese leichte Neufassung einen Unterschied gemacht hat. – gordyr

+0

@ Gordyr Können Sie uns den Code geben, der die Funktion switchImage() aufruft, um mir einen Kontext zu geben? –

Antwort

3

Ihre ursprüngliche Funktion wäre direkt in eine Endlosschleife gegangen, wenn Sie nicht $(this).remove() hätten. Im Wesentlichen haben Sie das Attribut src auf alleimg Tags gesetzt, einschließlich des Preload-Images. (Ersetzen $(this).remove() mit console.log('loaded') und Schleife beobachtet unendlich in Firebug)

Ich würde vermuten, dass in IE8, sobald das Attribut auf das Preload-Image festgelegt ist auch, es aufgerufen Ihre ‚Last‘ Event-Handler zuerst vor der Ausführung nächste Zeile, die $(this).remove() (Erläuterung des Stack-Überlaufs) ist, während andere Browser zuerst die Ausführung der gesamten Funktion zuerst beendet haben, wodurch das Preload-Image entfernt wurde, wodurch die Endlosschleife verhindert wurde.(Dies ist nur eine Schätzung)

Ein Affe Patch auf die ursprüngliche Version wäre .find('img:not(#preload)') anstelle von nur .find('img') zu verwenden.

Ihr Patch verhindert auch die Endlosschleife, weil .one() dafür sorgt, dass es nur einmal ausgeführt wird.

Aber letztendlich würde ich die Funktion der folgenden Refactoring:

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

Beachten Sie auch, dass die Vorspannung Bild tatsächlich nicht explizit auf das DOM angehängt werden muss Ihren Zweck zu dienen.

Verwandte Themen