Chrome / jQuery Uncaught RangeError: Przekroczono maksymalny rozmiar stosu wywołań

113

W przeglądarce Chrome pojawia się błąd „Uncaught RangeError: maksymalny rozmiar stosu wywołań przekroczony”. oto moja funkcja jQuery

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

Zwróć uwagę, że strona zawiera dziesiątki tysięcy komórek. Generalnie jednak przepełnienie stosu kojarzy mi się z rekurencją iw tym przypadku, o ile widzę, nie ma jej.

Czy tworzenie takiej lambdy automatycznie generuje ładunek rzeczy na stosie? czy jest jakiś sposób na obejście tego?

W tej chwili jedynym rozwiązaniem, jakie mam, jest jawne generowanie zdarzeń onclick w każdej komórce podczas renderowania kodu HTML, co sprawia, że ​​kod HTML jest znacznie większy.

Andy
źródło
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 podczas komentowania foo($('#docId').val(), $(this).attr('id'));linii? - Dodatkowa wskazówka dotycząca wydajności: buforuj wyniki selektorów - na przykład zachowaj wynik $(this)w zmiennej i używaj go w razie potrzeby w module obsługi.
WTK
Mam podobny problem, ale potrzebuję wydarzeń mouseenter. Podczas korzystania z body lub table nie mam wystarczającej liczby zdarzeń.
ericslaw

Odpowiedzi:

133

Ponieważ „strona zawiera dziesiątki tysięcy komórek”, powiązanie zdarzenia kliknięcia z każdą pojedynczą komórką spowoduje straszny problem z wydajnością. Jest na to lepszy sposób, polegający na przypisaniu zdarzenia kliknięcia do treści, a następnie sprawdzeniu, czy element komórki był celem kliknięcia. Lubię to:

$('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 Twoje zadanie z natywnym tagiem „td”, ale także z dołączonym później „td”. Myślę, że zainteresuje Cię ten artykuł o wiązaniu wydarzeń i delegowaniu


Lub możesz po prostu użyć metody „ .on () ” jQuery z tym samym efektem:

$('body').on('click', 'td', function(){
        ...
});
vantrung -cuncon
źródło
dzięki, i tak walczymy o wydajność, więc to świetny pomysł :-)
Andy
60
Nieee, nie używaj .live () !!! bitovi.com/blog/2011/04/… Użyj .delegate () (lub .on (), jeśli Twoja jQuery jest wystarczająco nowa) i deleguj z poziomu tabeli, a nie całego dokumentu. Poprawi to wydajność znacznie bardziej niż tylko użycie .live (), które zasadniczo spowoduje delegację całego dokumentu w dół.
brandwaffle
19
A .live został usunięty z jQuery 1.9
cpuguy83
37

Możesz również otrzymać ten błąd, gdy masz nieskończoną pętlę. Upewnij się, że nie masz żadnych niekończących się, rekurencyjnych odwołań do siebie.

John Durden
źródło
6
To rozwiązało mój problem. Miałem <a id="linkDrink" onclick="drinkBeer();">Drink</a>i $('#linkDrink').click();in drinkBeer().
Aycan Yaşıt
7

Mój był raczej błędem, co się wydarzyło, to kliknięcie w pętli (tak sądzę), w zasadzie po kliknięciu loginu, na który kliknięto również rodzica, co zakończyło się przekroczeniem maksymalnego rozmiaru stosu wywołań.

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

<li class="clickhere">
  <a href="#" class="login">login</a>
</li>
Jsonras
źródło
3

Ten problem wystąpił ze mną, gdy użyłem jQUery Fancybox w witrynie z wieloma innymi wtyczkami jQuery. Kiedy użyłem LightBox ( strona tutaj ) zamiast Fancybox, problem zniknął.

Silvio Delgado
źródło
1

Możesz użyć

  $(document).on('click','p.class',function(e){
   e.preventDefault();
      //Code 
   });
demenvil
źródło
0

Niedawno właśnie napotkałem ten problem. Miałem bardzo dużą tabelę w oknie dialogowym div. Było> 15 000 rzędów. Po wywołaniu .empty () w oknie dialogowym div, otrzymałem powyższy błąd.

Znalazłem ogólne rozwiązanie, w którym przed wywołaniem czyszczenia okna dialogowego usunąłem co drugi wiersz z bardzo dużej tabeli, a następnie wywołałem .empty (). Wydawało się jednak, że zadziałało. Wygląda na to, że moja stara wersja JQuery nie radzi sobie z tak dużymi elementami.

dev4life
źródło