Für ein kleines Webprojekt habe ich ein paar Formular-Überprüfungen mit JavaScript geschrieben. Darunter ist eine, die eine Datenbankabfrage erfordert. Je nach Erfolg dieser Abfrage, soll das eigentliche Submit der Form ausgeführt werden, anderenfalls eine Fehlermeldung. Natürlich sollte es möglichst ohne separaten Server-Roundtrip mit jquery und Ajax realisiert sein.
Dabei ergibt sich allerdings ein Problem: Dummerweise ist Ajax asynchron, das heißt, die Antwort des Servers liegt zur Laufzeit des Scriptes nicht vor. Es liefert also immer false zurück, weil es die Antwort des Servers nicht abwartet. Ein Submit der Form findet nicht statt. Es ist gar nicht so leicht, JavaScript dazu zu bringen, auf das Ergebnis der Query zu warten. Künstliche Warteschleifen sind eine sehr unschöne Lösung (die den Browser außerdem heftig belasten). Man kann Ajax auch in einen Synchronous-Modus schalten, aber muss dann alles „zu Fuß“ programmieren und kann jquery nicht mehr verwenden. Außerdem hat der Synchronous-Modus starke Probleme bei der Browser-Kompatiblität.
Ich habe eine andere Lösung gefunden: Gar nicht erst warten. Das Script liefert false zurück und beendet sich. Der Teil des Scripts, der im Hintergrund die Datenbankabfrage vornimmt, läuft aber asynchron weiter. Dieser im Hintergrund laufende Teil des Scripts wartet darauf, dass die Datenbankabfrage eine Antwort geliefert hat und gibt genau dann je nach Bedarf eine Fehlermeldung aus oder stößt das Submit-Event einfach nochmal an.
Im HTML:
<form action="submit.php" method="post" id="myform" onSubmit="return checkForm(this);">
Im JavaScript:
function checkForm(form) { if ($.formLoading != false) { $.post('dbtest.php', { val1:form.elements["val1"].value , val2:form.elements["val2"].value }, function(response) { if (response == "1") { $.formLoading = false; $("#myform").submit(); } else { alert ("Eine Fehlermeldung."); } }); return false; } else { return true; } }
Damit das Script im Falle eines Erfolgs auch true zurückliefern kann, um das Submit auszulösen, wird noch eine Variable benötigt, die sich merkt, ob das Script schon einmal aufgerufen wurde: $.formLoading. Weil eine normale Variable die Laufzeit des Scriptes nicht überleben würde, wird sie kurzerhand ins DOM der zugehörigen Webseite gehängt.