JavaScript Besteht StackOverflow-Gefahr mit Ajax?

Physikbuddha

Lt. Commander
Registriert
Aug. 2014
Beiträge
1.062
Moin zusammen,

ich sitze grad an Javascript-Code, der Werte vom Server asynchron erhalten soll.
Die Updatemethode soll, nachdem sie einen Wert erhalten hat, wieder erneut am Server lauschen.
Das ganze sieht dann so aus:

Javascript:
function updateValueHandler() {
    $.ajax({
        url: "/api/update",
        type: "POST",
        success: function(result) {
            // result wird hier ausgewertet
            updateValueHandler();
        }
    });
}

Jetzt frage ich mich: Besteht hier die Gefahr eines Stackoverflows, da ich ja mehr oder weniger eine unendliche Rekursion habe, oder ist meine Befürchtung dank des success-Callbacks unbegründet?
Ansonsten hätte ich einfach ein window.setTimeout(updateValueHandler, 0); verwendet.

Hat da jemand von euch genug Wissen?
Würde mir den Abend retten.

Als Info: Im Hintergrund sitzt ein Tornado-Webserver mit asynchronem Framework. Der Ajax-Call zum Server bleibt so lange offen, bis der Server etwas neues zu berichten hat. Der Trigger erfolgt durch eine andere Seite, also quasi wie ein Chatprogramm. A schickt an Server, Server meldet an B.

Gruß vom Physikbuddha
 
Ein Stack Overflow kann auftreten (siehe hier). Warum verwendest du nicht einfach einen Timer?
 
Was macht denn der Timer besser?

Nochmal zum Verständnis, ich will die Methode nicht alle x Millisekunden aufrufen, sondern der Ajax-Call hängt beim Server, bis ein Update kommt. Das kann nach 20 Millisekunden sein, aber auch erst nach 10 Minuten.

Der Trigger kommt von einer zweiten Webseite, ich nenne sie mal Backend oder Dashboard. Dort werden Werte eingegeben. Dieses Backend läuft auf einem iPad, Laptop etc.
Das Frontend selber wird von einem Raspberry auf einem großen Bildschirm gezeigt, der im Raum hängt.
Mit dem Backend steuere ich nun, was im Frontend gezeigt wird.

Wenn nun der Bediener 10 Minuten keine Knöpfe drückt, dann hängt der Ajax-Call halt 10 Minuten in der Schwebe, bis er beendet wird.
Andererseits gibt es im Backend Knöpfe, die zwei Befehle direkt nacheinander mit 20 Millisekunden Verzögerung (als Sicherheitspuffer) senden.
 
dbeuebeb schrieb:
Ein Stack Overflow kann auftreten (siehe hier).
Da wäre ich mir nicht so sicher. Das ist ein anderer Fall. In deinem verlinkten Beispiel werden die Funktionen synchron aufgerufen. In seinem Code passiert das asynchron.

@Physikbuddha Probier es doch einfach mal aus, und lass es eine Stunde laufen. Ich bin mir relativ sicher, dass du durch den asynchronen Aufruf keinen Stack Overflow erhältst.
 
Uff, also schnell nen API-Endpunkt einrichten, der instantly nen Wert zurückgibt und den kleinen Sack mal ein bisschen stressen.

Ja gut, probier ich mal aus, ne?
 
Ja, genau. Muss ja auch keine Daten zurückgeben.
Alternativ nimmst du einfach die URL deines Dev Servers und machst ein GET /index.html. Hauptsache du kriegst die Antworten vom Server schön schnell.

Falls es nicht geht, kannst du deine asynchrone Funktion immer noch mit async/await synchronisieren, und eine normale Endlosschleife benutzen.
 
benneque schrieb:
Falls es nicht geht, kannst du deine asynchrone Funktion immer noch mit async/await synchronisieren, und eine normale Endlosschleife benutzen.

Müsst mal schauen, welche Browser das nativ unterstützen. Ich hab das zuletzt in einem fetten Projekt für ein KNX-Hausautomatisierungsgateway verwendet, allerdings mit Typescript. Und es musste IE11-kompatibel sein. Der Typescript-Compiler hat mein await-Zeugs dann in irgendwelche Gruselmethoden gepackt. Seitdem lehnt sich irgendwas in mir auf, wenn es um await und reines JS geht. :cool_alt:
 
Das mag auf den ersten Blick wie Rekursion mit Stackoverflow aussehen, du übergibst hier aber nur ein Funktions-Objekt, du ruftst den Funktionsobjekt-Code aber nicht aus dem $.ajax Kontext direkt rekursiv auf.
Achte auf die {} Klammern, das kennzeichnet das übergebene Funktionsobjekt, statt diesen Code direkt auszuführen.

In Wirklichkeit registriert dir $.ajax nur einen Listener „hey Ajax-Controller, ruf das hier auf, wenn der POST call fertig ist, ich geh derweil erstmal wieder“ und dann kehrt dein $.ajax sofort zurück. Füg dir mal zwischen Zeile 8 und 9 ein consolen-print-irgendwas ein, dann siehtst du was ich meine.

siehe auch:
http://jqfundamentals.com/chapter/ajax-deferreds
means that the $.ajax method returns before the request is finished, and therefore before the success callback runs. That means that this function's return statement runs before the request is complete.
 
Also, Fazit:
Chromes Devtools stürzen ab und schließen sich, sobald mehr als 32.768 gleiche Meldungen in die Console geprintet werden. :D

Mit einer direkten Rekursion drehen die Devtools dann komplett am Rad, bis ich nach 12300 Iterationen Uncaught RangeError: Maximum call stack size exceeded bekomme.
 
Es kann sein, dass der Browser-Thread nun wegen schneller Serviceantwortzeit so sehr mit JS Ausführung beschäftigt ist, dass der Browser die JS Ausführung irgendwann zwangsabbricht, weil kein Userinput mehr zum Zug kommt und der Browser dachte, das is gecrasht. Du brauchst evtl eine Verzögerung im erneuten Aufruf, sofern nicht der aufgerufene POST Service für eine verzögerte Antwort sorgt.
 
Doch doch, die JS-Ausführung läuft brav weiter, nur die Devtools schließen sich und die Console wird geleert.
Da dachte sich bestimmt ein Entwickler bei Google: Ach, für die Countervariable nehmen wir short. Niemand wird so verrückt sein, und mehr als 30k Meldungen in die Console hauen.

Aber sie haben mich noch nicht kennengelernt, ihren potentiellen Albtraumuser.
 
Ein asynchroner Callback läuft immer über den Event-loop in der VM. Immer wenn der Stack leer ist, wird der nächste Callback aus der Warteschlange vom Loop aufgerufen und abgearbeitet. Dabei legst du eventuell neue Callbacks in die Warteschlange (z.B. per ajax oder per setTimeout) und immer so weiter ;) Stackoverflow kann also nie passieren.
Die beste Erklärung, die ich bis jetzt gesehen habe ist die hier. Mit hübscher Animation und so :D
 
  • Gefällt mir
Reaktionen: new Account(), r15ch13 und Physikbuddha
Warum benutzt du nicht Websockets? Macht in deinem Fall mehr Sinn.
 
  • Gefällt mir
Reaktionen: boonstyle
Zurück
Oben