Chrome / jQuery Uncaught RangeError: tamanho máximo da pilha de chamadas excedido

113

Estou recebendo o erro "Uncaught RangeError: Tamanho máximo da pilha de chamadas excedido" no cromo. aqui está minha função jQuery

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

Observe que existem dezenas de milhares de células na página. No entanto, geralmente associo overflows de pilha com recursão e, neste caso, até onde posso ver, não há nenhum.

A criação de um lambda como esse gera automaticamente uma carga de coisas na pilha? existe alguma maneira de contornar isso?

No momento, a única solução que tenho é gerar os eventos onclick explicitamente em cada célula ao renderizar o HTML, o que torna o HTML muito maior.

Andy
fonte
2
Tem certeza de que a função foo não recursiva? O erro ainda ocorre se você remover essa chamada de função?
sth
1
Funciona como esperado em outros navegadores? Este erro ocorre quando você comenta a foo($('#docId').val(), $(this).attr('id'));linha? - Dica de desempenho extra: armazene o resultado dos seletores em cache - por exemplo, mantenha o resultado de $(this)em uma variável e, em seguida, use-o em seu manipulador conforme necessário.
WTK
Tenho um problema semelhante, mas preciso de eventos do mouseenter. Ao usar body ou table, não recebo eventos suficientes.
ericslaw

Respostas:

133

Como "há dezenas de milhares de células na página", vincular o evento de clique a cada célula causará um terrível problema de desempenho. Há uma maneira melhor de fazer isso, que é vincular um evento de clique ao corpo e, em seguida, descobrir se o elemento da célula foi o alvo do clique. Como isso:

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

Este método não apenas fará sua tarefa com a tag "td" nativa, mas também com "td" anexado posteriormente. Acho que você se interessará por este artigo sobre associação e delegação de eventos


Ou você pode simplesmente usar o método " .on () " do jQuery com o mesmo efeito:

$('body').on('click', 'td', function(){
        ...
});
vantrung -cuncon
fonte
obrigado, estamos lutando para ter um bom desempenho nisso de qualquer maneira, então esta é uma ótima ideia :-)
Andy
60
Nããão, não use .live () !!! bitovi.com/blog/2011/04/… Use um .delegate () (ou .on () se o seu jQuery for novo o suficiente), e delegue no nível da tabela em vez do documento inteiro. Isso melhorará seu desempenho muito mais do que apenas usar .live (), que basicamente apenas delegará de todo o documento.
brandwaffle de
19
E .live foi removido do jQuery 1.9
cpuguy83 de
37

Você também pode obter esse erro quando tiver um loop infinito. Certifique-se de que você não tenha nenhuma auto-referência recursiva interminável.

John Durden
fonte
6
Isso resolveu meu problema. Eu tive uma <a id="linkDrink" onclick="drinkBeer();">Drink</a>, e uma $('#linkDrink').click();no drinkBeer().
Aycan Yaşıt
7

O meu foi mais um erro, o que aconteceu foi um clique de loop (eu acho) basicamente clicando no login o pai também foi clicado, o que acabou causando o tamanho máximo da pilha de chamadas excedido.

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

<li class="clickhere">
  <a href="#" class="login">login</a>
</li>
Jsonras
fonte
3

Este problema aconteceu comigo quando usei o jQUery Fancybox dentro de um site com muitos outros plug-ins do jQuery. Quando usei o LightBox ( site aqui ) ao invés do Fancybox, o problema foi embora.

Silvio Delgado
fonte
1

Você pode usar

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

Recentemente, também encontrei esse problema. Eu tinha uma mesa muito grande na div de diálogo. Era> 15.000 linhas. Quando o .empty () foi chamado na caixa de diálogo div, eu estava recebendo o erro acima.

Eu encontrei uma solução circular onde antes de chamar a limpeza da caixa de diálogo, eu removeria todas as outras linhas da tabela muito grande e, em seguida, chamaria o .empty (). Mas parecia ter funcionado. Parece que minha versão antiga do JQuery não consegue lidar com elementos tão grandes.

dev4life
fonte