2012-05-17 11 views
6

Mam prostą funkcję, która powoduje błąd przepełnienia stosu w IE 8. Problem nie występuje w żadnej innej przeglądarce, chociaż nie testowałem IE 7 lub 6.Dlaczego moja funkcja jQuery powoduje błąd "Stack Overflow" w IE 8?

Dokładny błąd jest następujący: -

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

funkcja w pytaniu:

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

dać przegląd przypadku użycia będę wyjaśniać cel tej funkcji:

Gdy użytkownik zmienia rozmiar obrazu (przy użyciu rozmiaru JQueryUI), szerokość/wysokość jest porównywana z inną funkcją.

Po powiększeniu obrazu o określonej wielkości funkcja ta jest wywoływana, co jak widać dołącza ukryty element <img> do DOM z atrybutem "src" wersji obrazu o wyższej rozdzielczości (lub niższej jeżeli obraz jest zmniejszane przez użytkownika.

po załadowaniu atrybut src widocznego elementu jest aktualizowany i ukryty element jest usuwany.

okazało doskonałą dynamicznego przełączania obrazów jak zmienia rozmiar użytkowników ich zachowanie dobrej jakości obrazu w całym procesie ....

Po prostu nie mogę się domyślić, co powoduje problem w IE 8. Po usunięciu tej funkcji nie występują żadne błędy, a mimo że błąd jest obecny, funkcja nadal działa tak, jak powinna (mimo że w IE wydajność zmiany rozmiaru jest niska; 8).

Każda pomoc zostanie bardzo doceniona.

UPDATE: I wydaje się, że rozwiązał problem przez przepisywanie oryginalną funkcję na następujące kwestie: -

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

Jak widać, jedyną różnicą jest to, że używam .appendTo() zamiast metody .append(), a także metody jQuery .one(), aby upewnić się, że zdarzenie load występuje tylko raz. Chociaż element ten jest usuwany bezpośrednio po tym, nie rozumiem, dlaczego to powinno coś zmienić.

Naprawdę chciałbym się przekonać, czy ktokolwiek może rzucić jakiekolwiek światło na ten temat, aby dowiedzieć się, jak uniknąć takich problemów w przyszłości. Twoje zdrowie.

+0

Co stanie się, gdy używasz niezwiązanej wersji jQuery? Przynajmniej w ten sposób uzyskasz bardziej sensowne odniesienie do błędu. – RobG

+0

To samo się dzieje .... Uwierz lub nie po pięciu minutach od opublikowania pytania ... Rozwiązałem to. Ale nie mam pojęcia, dlaczego ... zaktualizuję moje pytanie, ponieważ naprawdę chciałbym zrozumieć, dlaczego ten drobny przepis zmienił sytuację. – gordyr

+0

@gordyr Czy możesz podać kod wywołujący funkcję switchImage(), aby podać kontekst? –

Odpowiedz

3

Twoja początkowa funkcja mogłaby uruchomić się w nieskończoną pętlę, jeśli nie masz $(this).remove(). Zasadniczo to, co robiłeś, to ustawianie atrybutu src na wszystkie znacznikiimg, łącznie z samym obrazem wstępnym. (Wymienić $(this).remove() z console.log('loaded') i obejrzeć go pętli nieskończenie w Firebug)

Przypuszczam, że w IE8, gdy atrybut jest ustawiony na obraz napięcia wstępnego, a także, że wywoływany swoją „obciążenie” pierwszy obsługi zdarzeń przed wykonywania operacji następna linia, która jest $(this).remove() (wyjaśniająca przepełnienie stosu), podczas gdy inne przeglądarki mogły najpierw zakończyć wykonywanie całej funkcji jako pierwszej, usuwając w ten sposób obraz wstępny, który uniemożliwił nieskończoną pętlę.(To tylko odgadnięcie)

Poprawka małpy do początkowej wersji będzie używać .find('img:not(#preload)') zamiast tylko .find('img').

Twoja poprawka zapobiega również nieskończonej pętli, ponieważ .one() zapewnia jej uruchamianie tylko raz.

Ale ostatecznie chciałbym byłaby funkcję do następujących:

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

Należy również zauważyć, że obraz preload faktycznie nie musi być jawnie dołączana do DOM służyć swój cel.

Powiązane problemy