Chrome / jQuery Uncaught RangeError: taille maximale de la pile d'appels dépassée

113

J'obtiens l'erreur "Uncaught RangeError: taille maximale de la pile d'appels dépassée" sur chrome. voici ma fonction jQuery

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

Notez qu'il y a des dizaines de milliers de cellules dans la page. Cependant, j'associe généralement les débordements de pile à la récursivité et dans ce cas, pour autant que je puisse voir, il n'y en a pas.

La création d'un lambda comme celui-ci génère-t-elle automatiquement une charge de choses sur la pile? y a-t-il moyen de contourner cela?

Pour le moment, la seule solution de contournement dont je dispose est de générer explicitement les événements onclick sur chaque cellule lors du rendu du HTML, ce qui rend le HTML beaucoup plus grand.

Andy
la source
2
Êtes-vous sûr que la fonction foo ne se répète pas? L'erreur se produit-elle toujours si vous supprimez cet appel de fonction?
STH
1
Fonctionne-t-il comme prévu dans d'autres navigateurs? Cette erreur se produit-elle lorsque vous commentez la foo($('#docId').val(), $(this).attr('id'));ligne? - Astuce de performance supplémentaire: mettez en cache le résultat des sélecteurs - par exemple, conservez le résultat de $(this)dans une variable et utilisez-le ensuite dans votre gestionnaire si nécessaire.
WTK
J'ai un problème similaire mais j'ai besoin d'événements mouseenter. Lorsque j'utilise body ou table, je n'obtiens pas assez d'événements.
ericslaw

Réponses:

133

Comme "il y a des dizaines de milliers de cellules dans la page", la liaison de l'événement de clic à chaque cellule causera un terrible problème de performances. Il existe un meilleur moyen de le faire, qui lie un événement de clic au corps et détermine ensuite si l'élément de cellule était la cible du clic. Comme ça:

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

Cette méthode ne fera pas seulement votre tâche avec la balise native "td", mais également avec "td" ajouté ultérieurement. Je pense que vous serez intéressé par cet article sur la liaison d'événements et les délégués


Ou vous pouvez simplement utiliser la méthode " .on () " de jQuery avec le même effet:

$('body').on('click', 'td', function(){
        ...
});
vantrung -cuncon
la source
merci, nous luttons pour la performance de toute façon, donc c'est une excellente idée :-)
Andy
60
Non, n'utilisez pas .live () !!! bitovi.com/blog/2011/04/ ... Utilisez un .delegate () (ou .on () si votre jQuery est assez récent), et déléguez à partir du niveau de la table plutôt que du document entier. Cela améliorera vos performances bien plus que la simple utilisation de .live (), qui ne déléguera essentiellement que le document entier.
brandwaffle
19
Et .live a été supprimé de jQuery 1.9
cpuguy83
37

Vous pouvez également obtenir cette erreur lorsque vous avez une boucle infinie. Assurez-vous de ne pas avoir de références personnelles interminables et récursives.

John Durden
la source
6
Cela a résolu mon problème. J'ai eu un <a id="linkDrink" onclick="drinkBeer();">Drink</a>, et un $('#linkDrink').click();in drinkBeer().
Aycan Yaşıt
7

Le mien était plus une erreur, ce qui s'est passé était un clic de boucle (je suppose) essentiellement en cliquant sur le login, le parent a également été cliqué, ce qui a fini par entraîner le dépassement de la taille maximale de la pile d'appels.

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

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

Ce problème m'est arrivé lorsque j'ai utilisé jQUery Fancybox dans un site Web avec de nombreux autres plugins jQuery. Lorsque j'ai utilisé la LightBox ( site ici ) au lieu de Fancybox, le problème a disparu.

Silvio Delgado
la source
1

U peut utiliser

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

J'ai récemment rencontré ce problème également. J'avais une très grande table dans la boîte de dialogue div. C'était> 15 000 lignes. Lorsque le .empty () a été appelé sur le div de dialogue, j'obtenais l'erreur ci-dessus.

J'ai trouvé une solution circulaire où avant d'appeler le nettoyage de la boîte de dialogue, je supprimais toutes les autres lignes de la très grande table, puis j'appelais le .empty (). Cela semblait cependant avoir fonctionné. Il semble que mon ancienne version de JQuery ne puisse pas gérer des éléments aussi volumineux.

dev4life
la source