Anzeige
Tutorialbeschreibung

Javascript und Ajax - Fehlerbehandlung

Javascript und Ajax - Fehlerbehandlung

Das nun folgende Tutorial ist ein Auszug aus der 7. Auflage des Buches: JavaScript und Ajax von Christian Wenz.

Kapitel 15 Fehlerbehandlung

Fehlermeldungen sind der größte Feind eines Programmierers. Versierte Anwender wissen, worum es sich handelt, und der Nimbus der Unfehlbarkeit ist weg. Nicht ganz so gut informierte Benutzer jedoch wissen gar nicht, wie ihnen geschieht, wenn beispielsweise der Internet Explorer ein Warndreieck und eventuell noch eine (nichtssagende – wie immer beim IE) Fehlermeldung zeigt.

Bestenfalls treten Fehlermeldungen gar nicht auf, weil jede Eventualität berücksichtigt worden ist und die Programmierung perfekt ist. Das ist jedoch selbst bei kleineren Programmierprojekten eine Illusion und im Web erst recht. Selbst, wenn Sie keinen Fehler bei der Programmierung gemacht haben, es wird immer eine bestimmte Browserversion unter einem bestimmten Betriebssystem geben, die Ihnen einen Strich durch die Rechnung macht und unter bestimmten Umständen eine Fehlermeldung produziert.

Bereits seit der JavaScript-Version 1.2 gibt es jedoch Möglichkeiten, solche so genannten syntaktischen Fehler (Verstöße gegen die JavaScript-Syntaxregeln) abzufangen, so dass der Benutzer dadurch wenigstens nicht mehr belästigt wird oder die Fehlermeldung besonders aufbereitet wird. Denn wenn der Benutzer schon auf einen Fehler stößt, dann ist es nur zu Ihrem Vorteil, wenn auch Sie davon erfahren!

Es gibt jedoch auch logische Fehler. Das sind Fehler, die zu keiner Fehlermeldung führen, aber dafür sorgen, dass das Skript ein falsches Ergebnis liefert. Diese Fehler sind erfahrungsgemäß am schwierigsten zu finden, eben weil der Fehler nur am Ergebnis sichtbar ist. Wenn Sie den Netscape Navigator einsetzen – was in Hinblick auf die Aussagekraft der Fehlermeldungen ohnehin vorteilhaft ist –, können Sie mit einem kostenlosen Tool von Netscape dem Fehlerteufel auf die Spur kommen. Der JavaScript Debugger lässt Sie während der Ausführung eines Skripts auf die Werte der Variablen zugreifen, und Sie können den Skriptablauf auch unterbrechen.


15.1 Fehler abfangen  

Beim Thema Event-Handler (siehe Kapitel 14) wurde auch kurz onerror vorgestellt, der beim Eintreten eines Fehlers aktiv wird. Es gibt drei Möglichkeiten, diesen Event-Handler einzusetzen:

gpBilder
 
<body onerror="Code">: Führt beim Auftreten eines Fehlers den angegebenen Code aus.
gpBilder
 
window.onerror = Funktionsreferenz: Führt die angegebene Funktion beim Auftreten eines Fehlers aus. Es muss eine Referenz auf die Funktion angegeben werden, also window.onerror = funktion und nicht window.onerror = funktion(). Alternativ können Sie eine anonyme Funktion verwenden: window.onerror = function() { /* Code */ }.
gpBilder
 
Eine Funktion namens onerror() wird definiert und dann automatisch ausgeführt, sobald ein Fehler auftritt.


15.1.1 Keine Fehlermeldung  

Wenn die Funktion, die beim Auftreten eines Fehlers ausgeführt werden soll, oder allgemein der Code, der dann zur Ausführung kommt, mit return true endet, wird der Fehler nicht angezeigt, und der Benutzer bleibt unbehelligt.

Dies soll an einem Beispiel kurz demonstriert werden. Normalerweise würde die folgende Anweisung zu einer Fehlermeldung führen, die Variable rhei ist nicht definiert. Da es jedoch eine Funktion onerror() gibt, die (immer) den Wert true zurückliefert, wird dieser Fehler verschluckt und nicht ausgegeben:

<html>
<head>
<title>Fehler abfangen</title>
<script type="text/javascript"><!--
function oe() {
   return true;
}
window.onerror = oe;

var pantha = rhei;
//--></script>
</head>
<body>
Na, wo ist der Fehler?
</body>
</html>


15.1.2 Besondere Fehlermeldung  

Wie bereits eingangs erwähnt wurde, kann man auch eine besondere Fehlermeldung ausgeben. An die Fehlerbehandlungsfunktion werden nämlich drei Parameter übergeben: die Fehlermeldung, die URL des Dokuments, in dem der Fehler auftrat, und die Zeile, in der das fehlerhafte Kommando steht. Mit der folgenden Strategie können Sie also eine angepasste Fehlermeldung ausgeben:

gpBilder
 
Zeigen Sie eine etwas »freundlichere« Fehlermeldung für Ihre Nutzer an.
gpBilder
 
Beenden Sie die Funktion mit return true, damit der Browser danach die Fehlermeldung nicht anzeigt.

Der folgende Code zeigt dies einmal exemplarisch. Der Fehler wird mittels window.alert() ausgegeben, natürlich mit einem beruhigenden Hinweis.

<html>
<head>
<title>Fehler abfangen</title>
<script type="text/javascript"><!--
function oe(meldung, url, zeile) {
   var txt = "Es ist ein Fehler aufgetreten! Das macht
      aber nichts...

";
   txt += "Meldung: " + meldung + "
";
   txt += "URL: " + url + "
";
   txt += "Zeile: " + zeile;
   alert(txt);
   return true;
}
window.onerror = oe;
var pantha = rhei;
//--></script>
</head>
<body>

Na, wo ist der Fehler?
</body>
</html>

Bilder

Abbildung 15.1     Die selbst gestrickte Fehlermeldung


15.1.3 Ausblick: Fehlermeldungen verschicken 
topBilder

Obwohl es sich bei diesem Buch um ein JavaScript-Buch handelt, ist ein Blick über den Tellerrand nicht schlecht. Am günstigsten wäre es doch, wenn eine JavaScript-Fehlermeldung dem Surfer nicht angezeigt, aber automatisch via E-Mail an den Autor der Seite (also an Sie) versandt würde.

Ein erster Ansatz ist ziemlich umständlich und nicht gerade professionell:

gpBilder
 
Öffnen Sie beim Auftreten einer Fehlermeldung mit window.open() ein neues Fenster.
gpBilder
 
Erstellen Sie mittels (vielen) document.write()-Anweisungen in dem neuen Fenster ein Formular, in dem Sie (z.  B.) als versteckte Formularfelder die interessanten Daten eintragen: Fehlermeldung, URL und Zeile.
gpBilder
 
Setzen Sie das action-Attribut des Formulars auf mailto:Ihre_ E-Mail@Ihr-Provider.de.
gpBilder
 
Fügen Sie in das Formular an geeigneter Stelle ein Kommando zum Versand des Formulars ein:
setTimeout("document.forms[0].submit(); window.close()",
   1000)
gpBilder
 
Das Formular wird nun automatisch via E-Mail versandt, und das neu erschaffene Browserfenster wird gleich wieder geschlossen.

Das ist ein toller Trick – aber er hat zwei Haken. Ich habe an anderer Stelle schon darauf hingewiesen, was von action="mailto:..." in Formularen zu halten ist (kurze Antwort: nichts), und der Besucher Ihrer Website wird auch nicht gerade erfreut sein, wenn ungefragt über sein Konto eine E-Mail an Sie versandt wird. Das Hauptmanko ist jedoch, dass aus Sicherheitsgründen bei den meisten Browsern Formular.submit() nicht funktioniert, wenn action auf mailto:... gesetzt ist. Aus diesem Grund finden Sie an dieser Stelle kein komplettes Skript, sondern dürfen sich in einer Übungsaufgabe damit herumschlagen.

Mit serverseitigen Mitteln ist das dagegen kein größeres Problem. Der Mail-Versand läuft auf Ihrem Webserver ab, der Benutzer bekommt (kaum) etwas mit. Es gibt hier elegante und weniger elegante Lösungen, und Sie sehen an dieser Stelle einen Mittelweg, der auf der Grundidee des vorherigen Ansatzes aufbaut. Es wird ein neues Fenster geöffnet, in diesem Fenster wird jedoch ein serverseitiges Skript aufgerufen, das die E–Mail versendet und dann das Fenster wieder schließt.

Das Hauptproblem ist die Überlegung, welche serverseitige Programmiersprache eingesetzt wird. Ich habe mich hier für Perl, PHP und JScript.NET entschieden. Perl ist eine lang bewährte Sprache, die aber im Vergleich mit jüngeren und einfacher zu erlernenden Konkurrenten wie beispielsweise ASP.NET und eben PHP (die beiden anderen verwendeten Sprachen), mehr und mehr an Boden verliert. Doch die meisten Webserver unterstützen Perl (vor allem die meisten Hoster). Das Skript lässt sich mit relativ wenig Aufwand in andere Sprachen umschreiben.

Zunächst betrachten wir den HTML- und JavaScript-Code. Beim Auftreten eines Fehlers wird ein neues Fenster geöffnet. In der URL werden die Fehlerdaten (wie gewohnt: Meldung, URL, Zeile) übergeben. In Kapitel 9 haben Sie ja schon gesehen, wie Sie Daten in der Kommandozeile übergeben können. Von besonderer Bedeutung ist noch der Dateiname des serverseitigen Skripts. Perl-Programme liegen meistens im Verzeichnis /cgi-bin und haben die Endung .pl oder .cgi.

Sie können dieses Skript nur testen, wenn Sie Ihren Webserver entsprechend konfiguriert haben, worauf an dieser Stelle aus Platzgründen nicht eingegangen wird. Wenn Sie ein Web-Angebot bei einem Hoster unterhalten, erhalten Sie dort weitere Hinweise.

<html>
<head>
<title>Fehler abfangen</title>
<script type="text/javascript"><!--
function oe(meldung, url, zeile) {
   var perl = "/cgi-bin/fehler.pl?";
   perl += "meldung=" + escape(meldung);
      //escape() nicht vergessen!
   perl += "&url=" + escape(url);
   perl += "&zeile=" + escape(zeile);
   window.open(perl, "Fehler", "width=100,height=100");
   return true;
}
window.onerror = oe;
var panta = rhei;
//--></script>
</head>
<body>
Na, wo ist der Fehler?
</body>
</html>

Nun zur Datei fehler.pl. Dieses Skript muss die folgenden Aufgaben erledigen:

gpBilder
 
die Daten aus der URL auslesen
gpBilder
 
diese Daten per E-Mail verschicken
gpBilder
 
ein HTML-Dokument ausgeben, das im Wesentlichen dafür sorgt, dass das Fenster wieder geschlossen wird

Das folgende Perl-Programm erledigt all diese Aufgaben. Sie müssen das Programm gegebenenfalls an Ihre Verhältnisse anpassen. Wenn Sie UNIX oder Linux einsetzen, müssen Sie in der ersten Zeile den kompletten Pfad zu Ihrem Perl-Interpreter angeben (normalerweise /usr/bin/perl, aber manchmal auch /usr/local/bin/perl oder Ähnliches). Das Programm Sendmail, das für den Versand der E-Mail sorgt, liegt in der Regel auch im Verzeichnis /usr/bin, aber auch dies kann sich ändern. Sie können auch den Hauptkonkurrenten von Sendmail, qmail, einsetzen.

#!/usr/bin/perl
$fehler = $ENV{'QUERY_STRING'};
@namevalue = split(/&/, $fehler);
foreach $i (@namevalue){
   $i =~ tr/+/ /;
   $i =~ s/%(..)/pack("C", hex($1))/eg;
   ($name, $value) = split(/=/, $i);
   $fehler{$name} = $value;
}

open(SENDMAIL, "|/usr/bin/sendmail -t");
print SENDMAIL "From: betatester@xy.de
";
print SENDMAIL "To: bugfixer@xy.de
";
print SENDMAIL "Subject: JavaScript-Fehler!

";
print SENDMAIL "Fehlermeldung: " . $fehler{'meldung'}
. "
";
print SENDMAIL "URL: " . $fehler{'url'} . "
";
print SENDMAIL "Zeile: " . $fehler{'zeile'} . "
";
close SENDMAIL;
print <<'EOF';
<html>
<head>
<title>Fehler entdeckt!</title>
<script type="text/javascript"><!--
window.close();
//--></script>
</head>
<body>Einen Moment bitte ...</body>
</html>
EOF

Tritt nun ein JavaScript-Fehler auf, so öffnet sich für kurze Zeit das neue Browserfenster, eine E-Mail wird versandt, und das Fenster wird wieder geschlossen. So einfach ist das (mehr oder weniger)!

Die PHP-Version kann in etwa wie folgt aussehen:

<?php
$meldung = (isset($_GET['meldung'])) ? $_GET['meldung'] : '';
$url = (isset($_GET['url'])) ? $_GET['url'] : '';
$zeile = (isset($_GET['zeile'])) ? $_GET['zeile'] : '';
$mailtext  = "Fehlermeldung: $meldung
";
$mailtext .= "URL: $url
";
$mailtext .= "Zeile: $zeile
";
mail("bugfixer@xy.de", "JavaScript-Fehler!",
$mailtext, "");
?>
<html>
<head>
<title>Fehler entdeckt!</title>
<script type="text/javascript"><!--
  window.close();
//--></script>
</head>
<body>Einen Moment bitte ...</body>
</html>

Die Datei muss die Endung .php haben, und der Webserver muss natürlich für die Unterstützung von PHP korrekt konfiguriert sein!

Zu guter Letzt folgt hier noch die ASP.NET-Seite auf Basis von JScript .NET:

<%@ Page Language="JScript" %>
<%@ Import Namespace="System.Web.Mail" %>
<script runat="server">
function Page_Load() {
  SmtpMail.SmtpServer = "localhost";
  SmtpMail.Send(
    "besucher@xy.de",
    "bugfixer@xy.de",
    "JavaScript-Fehler!",
    "Fehlermeldung: " + Request.QueryString["meldung"] +
System.Environment.NewLine +
    "URL: " + Request.QueryString["url"] +
System.Environment.NewLine +
    "Zeile: " + Request.QueryString["zeile"]);
}
</script>
<html>
<head>
<title>Fehler entdeckt!</title>
<script type="text/javascript"><!--
  window.close();
//--></script>
</head>
<body>Einen Moment bitte ...</body>
</html>

15.2 JavaScript Debugger  

Unter http://www.mozilla.org/projects/venkman/ stellt das Mozilla-Projekt einen kostenlosen Debugger für JavaScript-Programme zur Verfügung. Dieser bietet die Basiseigenschaften eines Debuggers, also das Setzen von Breakpoints und die Anzeige aktueller Variablenwerte während der Ausführung (dazu jeweils später mehr). Nach der Installation integriert sich der Debugger in das Menü des Browsers und kann per Extras N JavaScript Debugger gestartet werden.

Bilder

Abbildung 15.2     Der Bildschirm nach dem Starten des Debuggers


15.2.1 Wo ist der Fehler?

Nun benötigen wir noch ein fehlerhaftes Programm. Kaufen Sie also ein Konkurrenzwerk (war nur ein Scherz), oder werfen Sie einen Blick auf das folgende kurze Programm:

<html> <head> <title>Debugger</title> <script type="text/javascript"><!-- var summe = 0; var zaehler = 0; var obergrenze; function ungerade() { zaehler++; var summe = summe + zaehler; if (zaehler < obergrenze) { gerade(); } } function gerade() { zaehler++; var summe = summe + zaehler; if (zaehler<obergrenze) { ungerade(); } } function sum(n) { obergrenze = n; ungerade(); return summe; } //--></script> </head> <body> <script type="text/javascript"><!-- document.write(sum(100)); //--></script> </body> </html>

Das Prinzip des obigen Programms ist relativ einfach. Die Hauptfunktion ist sum(n), die die Summe der Zahlen von 1 bis n berechnet. Um das Ganze ein wenig komplizierter (und damit fehlerträchtiger) zu machen, gehen wir wie folgt vor: In der globalen Variable summe wird das aktuelle Zwischenergebnis gespeichert, und in der globalen Variable zaehler merkt sich das Programm, welche Zahlen bis jetzt schon aufsummiert worden sind. Zunächst wird die Funktion ungerade() aufgerufen, die zunächst den Zähler um 1 erhöht (beim ersten Aufruf: auf 1) und dann den Wert des Zählers zur Zwischensumme addiert. Danach wird die Funktion gerade() aufgerufen, die genau dasselbe erledigt: zunächst Zähler erhöhen (beim ersten Aufruf: auf 2) und dann den Zählerwert zur Zwischensumme hinzuzählen. Sobald der Zähler die Obergrenze erreicht hat, wird abgebrochen.

Wenn man der Legende Glauben schenkt, hat Gauß schon im Grundschulalter diese Aufgabe gelöst. Sein Lehrer wollte ihn ein wenig beschäftigen und bat ihn, die Zahlen von 1 bis 100 zu addieren. Der kleine Gauß hat eine Weile überlegt und herausgefunden, dass man die Summe der Zahlen von 1 bis n mit der Formel n(n+1) berechnen kann; bei n=100 kommt 5050 heraus.

Wenn Sie das Skript im Browser aufrufen (starten Sie vorher unbedingt den Debugger, wie oben beschrieben!), werden Sie jedoch erstaunt feststellen, dass als Ergebnis 0 angezeigt wird. Woran kann das liegen?

Der Debugger weiß hier vielleicht Rat. Starten Sie den Debugger, so Sie im oberen Bereich unter anderem die (absichtlich) fehlerhafte Datei entdecken. Klicken Sie doppelt auf den Dateinamen, und der Quellcode erscheint (falls nicht, wählen Sie die Menüoption View N Show/Hide N Source Code).

Bilder

Abbildung 15.3     Der Quellcode im Debugger


15.2.2 Breakpoints  

Um den Debugger wirklich nutzen zu können, müssen Sie einen so genannten Breakpoint setzen. Die wörtliche Übersetzung, »Unterbrechungspunkt« oder auch »Haltepunkt«, kommt der Wahrheit schon sehr nahe. Sobald der JavaScript-Interpreter beim Haltepunkt angekommen ist, wird die Skriptausführung unterbrochen und Sie können beispielsweise auf den aktuellen Wert aller Variablen zugreifen.

Breakpoints beziehen sich immer auf eine Zeile; die Programmausführung wird unterbrochen, bevor der Code in der Zeile ausgeführt wird. Prinzipiell gibt es zwei Möglichkeiten, einen Breakpoint zu setzen:

gpBilder
 
Klicken Sie in die entsprechende Zeile, und wählen Sie im Kontextmenü (rechte Maustaste) den Eintrag Set Breakpoint.
gpBilder
 
Klicken Sie in der entsprechenden Zeile in den dunkelgrauen Bereich am linken Rand.

Egal welche der beiden Methoden Sie einsetzen, Sie sehen danach eine rote Markierung im linken Rand, wodurch das Vorhandensein eines Breakpoints angedeutet wird.

In diesem Beispiel sollten Sie den Breakpoint in die Zeile zaehler++ der Funktion ungerade() setzen. Tun Sie das, und laden Sie im Browserfenster das (fehlerhafte) Skript erneut. Nach kurzer Zeit kommt das Debugger-Fenster in den Vordergrund; die aktuelle Position der Skriptausführung ist durch eine gelbe Hintergrundmarkierung gekennzeichnet.


15.2.3 Watches  

Bilder

Abbildung 15.4     Watches werden in der Konsole angezeigt.

Es ist nun an der Zeit, die Werte einiger Variablen zu betrachten. Unter View N Show/Hide N Watches können Sie das Fenster für so genannte Watches einblenden, falls das noch nicht geschehen ist. Watches sind Variablen oder Ausdrücke, deren Wert Sie permanent überwachen möchten. Im Kontextmenü der Watches-Anzeige finden Sie den Eintrag Add Watch Expression, mit dem Sie eine neue Watch angeben können. Es empfiehlt sich in diesem Beispiel, ein genaueres Augenmerk auf die Variablen summe und zaehler zu werfen. Erstellen Sie also zwei Watches – eine für die Variable summe und eine für die Variable zaehler (alternativ können Sie auch im Fenster Locale Variables einen Wert auf alle lokalen Variablen werfen). Im Watches-Fenster werden die Variablennamen dann angezeigt, nebst allen zugehörigen Werten. Sobald sich der Wert einer der Variablen ändert, wird der neue Wert in der Konsole angezeigt. Sie müssen eigentlich nur noch das Programm weiterlaufen lassen (Schaltfläche Continue) und dabei zusehen, was geschieht.


15.2.4 Schrittweise Programmausführung 
topBilder

Sie sehen in der Symbolleiste ganz rechts fünf Schaltflächen, mit denen Sie die Skriptausführung wieder in Gang setzen können. Der Reihe nach haben diese die folgenden Funktionen:

gpBilder
 
Stop: Die Skriptausführung wird angehalten.
gpBilder
 
Continue: Das Programm wird weiter ausgeführt, bis es entweder am Ende ankommt oder wieder bei einem Breakpoint stehen bleiben muss.
gpBilder
 
Step Over: Es wird zur nächsten Zeile in der aktuellen Funktion gesprungen. Sollte der Interpreter am Ende der Funktion angelangt sein, verhält sich die Schaltfläche wie Run.
gpBilder
 
Step Into: Es wird zur nächsten Zeile des Programmcodes gesprungen, ganz egal, ob diese innerhalb der aktuellen Funktion liegt oder außerhalb.
gpBilder
 
Step Out: Die aktuelle Funktion wird verlassen und das Programm weiter ausgeführt, bis es endet oder am nächsten Breakpoint stehen bleiben muss.
gpBilder
 
Profile: Es wird ein so genanntes Profiling des Skripts durchgeführt: Welcher Teil dauert wie lange?
gpBilder
 
Pretty Print: Quellcode wird »hübsch« formatiert.

Beachten Sie nun genau, was geschieht, wenn Sie von der Zeile zaehler++ aus mit Step Into weiter vorgehen. Anfangs hat zaehler einen Wert von 0 und summe einen Wert von void. Nach der Ausführung des Kommandos zaehler++ hat zaehler den Wert 1, der Wert von summe hat sich nicht geändert. In der nächsten Zeile jedoch ändert sich der Wert von summe – aber nicht wie erhofft in 1, sondern in ... NaN, not a number. Warum nur?

Mit ein wenig Überlegung ist klar, wo der Fehler liegt. Vor der Anweisung summe = summe + zaehler steht ein var. Dadurch wird summe innerhalb der Funktion ungerade() – und analog dazu auch in gerade() – zu einer lokalen Variablen, deren Wert außerhalb der Funktion nicht sichtbar ist. Die Variable summe ist aber eigentlich als globale Variable konzipiert.

Bilder

Abbildung 15.5     Die Variable summe hat offensichtlich einen falschen Wert.

Entfernen Sie sowohl in der Funktion ungerade() als auch in der Funktion gerade() das Schlüsselwort var vor summe, brechen Sie im Debugger die Skriptausführung ab, und laden Sie die Seite im Browser neu. Ein Blick in den Debugger verheißt Gutes, denn nun wird summe anständig erhöht. Und wenn Sie nun noch den Breakpoint entfernen (zweimal in den dunkelgrauen Bereich klicken) und das Skript durchlaufen lassen, sehen Sie im Browser auch das korrekte Ergebnis – 5050. Wir haben zwar etwas länger gebraucht als der kleine Gauß, aber dafür durften wir ja auch nicht per Hand rechnen.





Das Tutorial ist ein Auszug aus der 7. Auflage des Buches von Christian Wenz:

JavaScript und Ajax - Das umfassende Handbuch
Galileo Computing, 853 Seiten, 8. aktualisierte Auflage

Die Veröffentlichung des Kapitels erfolgt mit freundlicher Genehmigung von Galileo Press.

Mehr Informationen zum aktualisierten Fachbuch für Webentwickler gibt es hier: JavaScript und Ajax
 
Alle Kapitel des Buches:
1 Grundlagen
2 JavaScript-Praxis
3 Professionelles JavaScript
4 Web 2.0 und Ajax
5 Kommunikation
6 Serverseitige Programmierung
7 Sicherheit
8 Praxis
9 Anhang
Bilder


 

DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von tanzfrosch
  • 11.01.2018 - 14:55

Dankeschön, tolles Tut. !

x
×
×