wake-up-neo.com

Ein "zu viel Rekursion" Fehler in Firefox nur manchmal?

Ich habe eine ziemlich einfache Sache, die ich mit Javascript mache, und im Grunde gibt mir Javascript nur manchmal einen "zu viel Rekursions" -Fehler.

Der fragliche Code:

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();
});

(Ja, ich weiß, dass es einen besseren Weg gibt, dies zu tun. Dies ist jedoch schwierig zu ändern, insbesondere aufgrund von ASP.Net-Teil-Postbacks, die nicht angezeigt werden.).

Wie auch immer, wenn der zu viele Rekursionsfehler auftritt, geschieht dies so lange, bis ich Firefox neu starte. Wenn ich Firefox neu starte, funktioniert alles wieder wie gewohnt. Wie behebe ich das?

Ich habe auch ein Jsbin-Beispiel gemacht

Update

Ok, ich habe herausgefunden, wie man es zuverlässig in unserem Code reproduziert, aber es funktioniert nicht für das Jsbin-Beispiel. Wenn ich einen neuen Tab erstelle und auf dieselbe Seite gehe (zwei Tabs mit derselben Adresse habe) und dann den ersten Tab zwei mal aktualisiere, wird dieser Fehler konsistent angezeigt. Wir verwenden keine Sitzung oder irgendetwas anderes, was mir einfällt, was dazu führen könnte, dass ein solches Problem nur auf einer Registerkarte auftritt!

Update 2 Nicht so zuverlässig wie ich dachte, aber es tritt definitiv nur auf, wenn mehr als ein Tab auf derselben Seite geöffnet ist. Es wird alle paar Nachladevorgänge einer der geöffneten Registerkarten auftreten

Ich habe außerdem meinen Code aktualisiert, um eine Warnung anzuzeigen, wenn pageLoad (die if-Anweisung) anfänglich undefiniert ist und wenn sie anfänglich definiert ist. Irgendwie werden beide Warnungen angezeigt. Dieser Code wird in der gerenderten Seite nicht dupliziert und kann auf keinen Fall zweimal aufgerufen werden. Es befindet sich in einem Skriptelement der höchsten Ebene, das nicht von einer Funktion oder etwas anderem umgeben ist! Mein Code sieht am Ende so aus

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

Der fragliche Code - von selbst - sollte niemals zu einem unendlichen Rekursionsproblem führen - es gibt keine Funktionsanweisung und alle Funktionsobjekte werden den Variablen eifrig zugewiesen. (Wenn pageload zuerst undefiniert ist, wird eine No-Operation-Funktion zugewiesen, siehe nächster Abschnitt.)

Ich vermute, es gibt zusätzlichen Code/Ereignisse, die das Verhalten auslösen. Kann kann dazu führen, dass das Skript/der Code zweimal während einer Seitenlebensdauer ausgelöst wird. Das 2. Mal pageload ist nicht undefiniert und behält den ursprünglichen Wert. Wenn die Funktion die beiden anderen Funktionen aufruft, führt dies zu einer unendlichen Rekursion.

Ich würde empfehlen, den Ansatz aufzuräumen - und Probleme, die durch die Komplikationen verursacht werden, verschwinden einfach ;-) Was ist die gewünschte Absicht?

Glückliche Kodierung.

6
user166390

Dies sind nur einige zusätzliche Informationen für andere Benutzer, die versuchen, nach ähnlichen Fehlern mit zu viel Rekursion in ihrem Code zu suchen. Es sieht so aus, als würde Firefox (als Beispiel) in diesem Beispiel bei 6500 Stack-Frames zu viel Rekursion erhalten: function moose(n){if(n%100 === 0)console.log(n);moose(n+1)};moose(0). In ähnlichen Beispielen werden Tiefen zwischen 5000 und 7000 angezeigt. Sie sind sich nicht sicher, was die bestimmenden Faktoren sind, aber es scheint, dass die Anzahl der Parameter in der Funktion die Stack-Frame-Tiefe drastisch verringert, bei der der Fehler "zu viel Rekursion" angezeigt wird. Dies führt beispielsweise nur zu 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)

Wenn Sie dieses Problem umgehen möchten, können Sie setTimeout verwenden, um Iterationen so zu planen, dass sie vom Scheduler fortfahren (wodurch der Stack zurückgesetzt wird). Dies funktioniert natürlich nur, wenn Sie aus dem Anruf nichts zurückgeben müssen:

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

Richtige Tail Calls in ECMAScript 6 lösen das Problem in einigen Fällen, in denen Sie etwas von solchen Aufrufen zurückgeben müssen. Bis dahin werden für Fälle mit tiefer Rekursion nur die Iteration oder die von mir erwähnte setTimeout-Methode verwendet.

2
B T

Ich bin auf diesen Fehler gestoßen. In meinem Fall war das Szenario anders. Der Tätercode war so ähnlich (was die rezessiv einfache Verkettung ist)

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

Ich habe festgestellt, dass JavaScript einen Fehler bei der 180. Rekursion ausgibt. Bis 179 Schleife läuft der Code gut.

Das Verhalten in Safaris ist genau das gleiche, außer dass der Fehler "RangeError: Maximale Aufrufstackgröße überschritten" ist. Es wirft diesen Fehler auch bei 180 Rekursion.

Dies bezieht sich zwar nicht auf den Funktionsaufruf, aber es kann jemandem helfen, der daran festhält.

1
Hammad Khan

Das wird auch das Problem "zu viel Rekursion" verursachen:

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();

Die Verwendung eindeutiger Namen ist wichtig.

Ok, warum passiert das?

In der set-Funktion wird die Eigenschaft nicht wirklich auf Menge gesetzt, sondern es wird die set-Funktion erneut aufgerufen, da sie im Bereich der set-Funktion dieselbe Syntax hat, sowohl für das Setzen der Eigenschaft als auch für das Aufrufen der set-Funktion.

Da in diesem Bereich this dasselbe ist wie account, kann (account OR this).balance = amount die Set-Funktion OR aufrufen und die Eigenschaft setzen.

Die Lösung hierfür ist, einfach den Namen der Eigenschaft oder der Set-Funktion auf irgendeine Weise zu ändern (und natürlich den Rest des Codes entsprechend zu aktualisieren).

0
Sebastian Norr

Afaik, dieser Fehler kann auch auftreten, wenn Sie einen falschen Parameter für Ihre Ajax-Anfrage angeben, wie z

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

Was sollte dann sein

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

stattdessen.

0
Blauhirn