2011-10-05 8 views
94

Otrzymuję komunikat "Uncaught RangeError: Przekroczono maksymalny rozmiar stosu połączeń" na chrome. tutaj jest moja funkcja jQueryChrome/jQuery Uncaught RangeError: Przekroczono maksymalny rozmiar stosu wywołań

$('td').click(function() { 
     if ($(this).context.id != null && $(this).context.id != '') { 
      foo($('#docId').val(), $(this).attr('id')); 
     } 
     return false; 
    }); 

pamiętać, że istnieją dziesiątki tysięcy komórek na stronie. Jednak generalnie kojarzę przepełnienie stosu z rekursją iw tym przypadku, o ile widzę, nie ma.

Czy tworzenie lambda w ten sposób automatycznie generuje ładunek materiału na stosie? czy jest jakikolwiek sposób wokół tego?

W tej chwili jedynym sposobem obejścia problemu jest wygenerowanie zdarzeń onclick jawnie dla każdej komórki podczas renderowania kodu HTML, co powoduje, że kod HTML jest znacznie większy.

+2

Czy na pewno funkcja foo nie powtarza się? Czy błąd nadal występuje, jeśli usuniesz to wywołanie funkcji? – sth

+1

Czy działa zgodnie z oczekiwaniami w innych przeglądarkach? Czy ten błąd występuje, gdy skomentujesz 'foo ($ ('# docId'). Val(), $ (this) .attr ('id'));' linia? - Dodatkowa wskazówka dotycząca wydajności: buforuj wynik selektorów - na przykład zachowaj wynik '$ (this)' w zmiennej i używaj go w poprzek programu obsługi w razie potrzeby. – WTK

+0

Mam podobny problem, ale potrzebne są zdarzenia związane z mouseenter. Podczas używania ciała lub stołu nie dostaję wystarczającej ilości zdarzeń. – ericslaw

Odpowiedz

113

Ponieważ "na stronie znajdują się dziesiątki tysięcy komórek" powiązanie zdarzenia kliknięcia z każdą komórką spowoduje straszny problem z wydajnością. Jest lepszy sposób na zrobienie tego, czyli powiązanie zdarzenia kliknięcia z ciałem &, a następnie ustalenie, czy element komórki był celem kliknięcia. W ten sposób:

$('body').click(function(e){ 
     var Elem = e.target; 
     if (Elem.nodeName=='td'){ 
      //.... your business goes here.... 
      // remember to replace $(this) with $(Elem) 
     } 
}) 

Ta metoda nie tylko wykona zadanie z natywnym tagiem "td", ale także z dołączonym później "td". Myślę, że będziesz zainteresowany w tym artykule o event binding & delegate


Albo można po prostu użyć „.on()” metody jQuery z tym samym skutkiem:

$('body').on('click', 'td', function(){ 
     ... 
}); 
+0

dziękuję, i tak walczymy o wydajność, więc jest to świetny pomysł :-) – Andy

+57

Nooo, nie używaj .live() !!! http://bitovi.com/blog/2011/04/why-you-should-never-use-jquery-live.html Użyj .delegate() (lub .on(), jeśli twój jQuery jest wystarczająco nowy), i delegować z poziomu tabeli, a nie całego dokumentu. Poprawi to twoją wydajność o wiele bardziej niż tylko użycie .live(), która w zasadzie po prostu przenosi się z całego dokumentu w dół. – brandwaffle

+17

I .live został usunięty z jQuery 1.9 – cpuguy83

3

Ten problem akurat ze mną, kiedy używał jquery Fancybox na stronie z wieloma innymi wtyczkami jQuery. Kiedy użyłem LightBox (site here) zamiast Fancybox, problem zniknął.

28

Ten błąd można również uzyskać, gdy masz nieskończoną pętlę. Upewnij się, że nie masz żadnych nieskończonych, rekursywnych odniesień własnych.

+3

To rozwiązało mój problem. Miałem 'Drink' i '$ ('# linkDrink'). Click();' in 'drinkBeer()'. –

4

Mój błąd był większym błędem, co się stało, to kliknięcie w pętlę (domyślam się) po kliknięciu na login został również kliknięty rodzic, co spowodowało przekroczenie maksymalnego rozmiaru stosu połączeń.

$('.clickhere').click(function(){ 
    $('.login').click(); 
}); 

<li class="clickhere"> 
    <a href="#" class="login">login</a> 
</li> 
1

U można używać

$(document).on('click','p.class',function(e){ 
    e.preventDefault(); 
     //Code 
    }); 
0

Niedawno wpadł właśnie tej kwestii, jak również. Miałem bardzo duży stół w oknie dialogowym div. To było> 15 000 wierszy. Kiedy funkcja .empty() została wywołana w oknie dialogowym div, otrzymałem błąd powyżej.

Znalazłem rozwiązanie dookoła, gdzie zanim wezwę czyszczenie okna dialogowego, usunęłbym co drugi wiersz z bardzo dużego stołu, a następnie zadzwonię do .empty(). Wyglądało na to, że zadziałało. Wygląda na to, że moja stara wersja JQuery nie radzi sobie z tak dużymi elementami.