web-dev-qa-db-fra.com

Une erreur "trop ​​de récursivité" dans Firefox seulement parfois?

J'ai une chose assez simple que je fais avec javascript et, fondamentalement, javascript ne me donne parfois qu'une erreur "trop ​​de récursivité".

Le code en question:

if(pageLoad===undefined){
  var pageLoad=function(){}; 
}
var pageLoad_uniqueid_11=pageLoad;
var pageLoad=function(){ 
  pageLoad_uniqueid_11();
  pageLoad_uniqueid_12(); 
};
var pageLoad_uniqueid_12=function(){
 alert('pageLoad');
};

$(document).ready(function(){
   pageLoad();
});

(Oui, je sais qu'il existe un meilleur moyen de procéder. Il est difficile de changer cela, en particulier à cause des publications partielles ASP.Net qui ne sont pas affichées).

Quoi qu'il en soit, lorsque l'erreur de récursion est trop fréquente, elle persiste jusqu'au redémarrage de Firefox. lorsque je redémarre Firefox, tout fonctionne à nouveau normalement. Comment puis-je réparer ça?

J'ai aussi créé un exemple de jsbin

Mise à jour

Ok, j'ai découvert comment le reproduire de manière fiable dans notre code, mais cela ne fonctionne pas pour l'exemple jsbin. Si je crée un nouvel onglet et va à la même page (avoir deux onglets de la même adresse) et puis actualise le premier onglet deux fois alors j'obtiens cette erreur systématiquement. Nous n'utilisons aucun type de session ou quoi que ce soit qui puisse causer un tel problème dans un seul onglet!

Mise à jour 2 Pas aussi fiable que je le pensais, mais cela ne se produit vraiment que lorsque plusieurs onglets de la même page sont ouverts. Il va se produire tous les quelques recharges d'un des onglets ouverts

J'ai également mis à jour mon code pour afficher une alerte lorsque pageLoad (l'instruction if) est initialement non défini et lorsqu'il est initialement défini. D'une manière ou d'une autre, les deux alertes apparaissent. Ce code n'est pas dupliqué dans la page rendue et il est impossible de l'appeler deux fois. C'est un élément de script de niveau supérieur qui n'est pas entouré d'une fonction ou quoi que ce soit! Mon code finit par ressembler

if(pageLoad===undefined){ 
  var pageLoad=function(){}; 
  alert('new'); 
} else {  
  alert('old'); 
}
12
Earlz

Le code en question - seul - devrait ne devrait jamais générer un problème de récursion infini - il n'y a pas d'instruction de fonction et tous les objets de fonction sont affectés aux variables avec impatience. (Si pageload est d'abord non défini, une fonction sans opération lui sera affectée, voir la section suivante.)

Je soupçonne qu'il y a du code/des événements supplémentaires qui déclenchent le comportement. Une chose que peut c'est parce que le script/code est déclenché deux fois pendant la durée de vie d'une page. La 2e fois pageload ne sera pas indéfinie et conservera la valeur d'origine, qui, si c'est la fonction qui appelle les deux autres fonctions, mènera à une récursion infinie.

Je recommanderais de nettoyer l'approche - et de résoudre tous les problèmes causés par les complications ;-) Quelle est l'intention souhaitée?

Bonne codage.

6
user166390

Il ne s'agit que de quelques informations supplémentaires pour les autres personnes cherchant des erreurs similaires "trop ​​de récursivité" dans leur code. On dirait que firefox (à titre d'exemple) obtient trop de récursivité à environ 6500 images de pile dans cet exemple: function moose(n){if(n%100 === 0)console.log(n);moose(n+1)};moose(0). Des exemples similaires peuvent indiquer des profondeurs comprises entre 5 000 et 7 000. Vous ne savez pas exactement quels sont les facteurs déterminants, mais il semble que le nombre de paramètres de la fonction diminue considérablement la profondeur de la pile à laquelle vous obtenez une erreur "trop ​​récursive". Par exemple, cela n'atteint que 3100:

function moose(n,m,a,s,d,fg,g,q,w,r,t,y,u,i,d){if(n%100 === 0)console.log(n);moose(n+1)};moose(0)

Si vous souhaitez contourner ce problème, vous pouvez utiliser setTimeout pour planifier des itérations à partir du planificateur (ce qui réinitialise la pile). Cela ne fonctionne évidemment que si vous n'avez pas besoin de renvoyer quelque chose de l'appel:

function recurse(n) {
  if(n%100 === 0)
    setTimeout(function() {
      recurse(n+1)
    },0)
  else
    recurse(n+1)
}

Les appels finaux appropriés dans ECMAScript 6 résoudront le problème dans certains cas où vous devez renvoyer quelque chose d'appels comme celui-ci. Jusque-là, pour les cas avec une récursion profonde, les seules réponses utilisent soit l'itération, soit la méthode setTimeout que j'ai mentionnée.

2
B T

Je suis tombé sur cette erreur. Le scénario dans mon cas était différent. Le code du coupable ressemblait à ceci (ce qui est une simple concaténation récessive)

while(row)
{
    string_a .= row['name'];
}

J'ai trouvé que JavaScript génère une erreur lors de la 180e récursivité. Jusqu'à la boucle 179, le code fonctionne bien.

Les comportements dans Safaris sont exactement les mêmes, sauf que l'erreur affichée est "RangeError: La taille maximale de la pile d'appels est dépassée". Il renvoie également cette erreur sur 180 récursivité.

Bien que cela ne soit pas lié à l'appel de fonction, cela pourrait aider quelqu'un qui en est pris au piège.

1
Hammad Khan

Cela provoquera également le problème de "trop ​​de récursivité":

class account {
    constructor() {
        this.balance = 0;      // <-- property: balance
    }

    set balance( amount ) {    // <-- set function is the same name as the property.
        this.balance = amount; // <-- AND property: balance (unintended recursion here)
    }
}

var acc = new account();

L'utilisation de noms uniques est importante.

Ok, alors pourquoi ça se passe?

Dans la fonction set, il ne s'agit pas de définir la propriété sur amount, mais d'appeler à nouveau la fonction set car, dans l'étendue de la fonction set, la syntaxe est la même pour définir la propriété ET appeler la fonction set.

Parce que dans cette étendue, this est identique à account et (account OR this).balance = amount peuvent tous deux appeler la fonction set OR définir la propriété.

La solution à cela est simplement de changer le nom de la propriété ou de la fonction set de quelque manière que ce soit (et bien sûr de mettre à jour le reste du code en conséquence).

0
Sebastian Norr

Cependant, cette erreur peut également apparaître si vous énoncez un paramètre incorrect pour votre demande ajax, comme

$.getJSON('get.php',{cmd:"1", elem:$('#elem')},function(data) { // ... }

Ce qui devrait alors être

elem:$('#elem').val()

au lieu.

0
Blauhirn