cpw: Überprüfen des Funktions-Status in AJAX aus anderer Funktion

Hallo,

ich habe ein kleines Problem mit AJAX, dessen Lösung ich momentan nur "hingepfuscht" bekomme...
Das ganze ist recht schwierig zu beschreiben, aber ich versuch's mal:

Folgendes Beispiel (tut nichts wirklich sinnvolles, soll nur das Problem verdeutlichen):

  
<html>  
<head>  
<script type="text/javascript">  
var ajax = null;  
  
    if (typeof XMLHttpRequest != 'undefined')  
    {  
        ajax = new XMLHttpRequest();  
    }  
  
 if (!ajax)  
 {  
     try  
     {  
         ajax = new ActiveXObject("Msxml2.XMLHTTP");  
     }  
  
     catch(e)  
     {  
  try  
  {  
      ajax = new ActiveXObject("Microsoft.XMLHTTP");  
  }  
  
  catch(e)  
  {  
      ajax = null;  
      window.alert('Ihr Browser unterstützt keine AJAX-Funktionalität. Wir empfehlen, einen aktuellen Browser zu verwenden.');  
  }  
     }  
 }  
  
  
var daten;  
  
function holeDaten()  
{  
    if(ajax)  
    {  
        ajax.open('POST', 'daten.xml', true);  
 ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");  
  
 ajax.onreadystatechange = function()  
 {  
     if(ajax.readyState == 4)  
     {  
         daten = ajax.responseXML.documentElement;  
     }  
 };  
  
 ajax.send(null);  
    }  
  
}  
  
holeDaten();  
  
  
function zeigMirDieDaten()  
{  
  
alert(daten.hasChildNodes());  
  
}  
  
zeigMirDieDaten();  
  
  
</script>  
</head>  
<body>  
</body>  
</html>  

Der Firefox sagt mir hier in der JavaScript-Console: "daten has no properties" - der Fehler wird vermutlich hervorgerufen, da zum Zeitpunkt an dem "zeigMitDieDaten()" aufgerufen wird, "holeDaten()" noch nicht fertig ist, also die Variable "daten" noch null ist.

Mein erster Gedanke: OK, mach ich's mit "SJAX", also setze ich doch einfach den Synchronisations-Parameter bei ajax.open() auf false - so sollte ja theoretisch mit der Ausführung des Skripts gewartet werden, bis alle Daten vollständig übertragen sind.

Im IE 7 funktioniert das - beim Laden der Seite erscheint das alert-Fenster mit "true" - der Firefox besteht weiterhin darauf, dass "daten" keine Properties hat.

Versuch zwei: "ajax" ist ja eine globale Variable, also müsste ich ja theoretisch auch in der "zeigMirDieDaten()"-Funktion Zugriff darauf haben und den "onreadystatechange"-Event abfragen können. Also ändere ich "zeigMitDieDaten()" folgendermaßen:

  
function zeigMirDieDaten()  
{  
    ajax.onreadystatechange = function()  
    {  
        if(ajax.readyState == 4)  
 {  
     alert(daten.hasChildNodes());  
  
 }  
    };  
}  

Hier passieren äusserst seltsame Dinge... der IE sagt nun: " 'daten' ist null oder kein Objekt" - obwohl das ja theoretisch in dieser Konstellation nicht mehr sein kann, die Daten müssen ja da sein...

Der Firefox zeigt keine JavaScript-Fehlermeldung an, tut aber auch sonst nix, hört also scheinbar nicht auf das "onreadystatechange" der "holeDaten()"-Funktion.

Methode drei: Der Rekursions-Holzhammer... :

  
function zeigMirDieDaten()  
{  
    try  
    {  
        alert(daten.hasChildNodes());  
    }  
  
    catch(e)  
    {  
        window.setTimeout("zeigMirDieDaten()", 250);  
    }  
}  

D.h. ich rufe die Funktion in bestimmten Zeitabständen einfach immer wieder rekursiv auf... funktioniert sowohl im IE als auch im FF, ist aber IMHO nicht die Lösung deluxe... vor allem dürfte diese Rekursion unendlich laufen, falls z.B. die "holeDaten()"-Funktion kein Daten vom Server bekommt. Der Firefox und der IE7 brechen irgendwann ab, der IE6 - und evtl. auch einige andere Browser - hängen sich dabei aber ganz gerne mal komplett weg.

Gibt's für sowas keine elegante Lösung, mit der ich irgendwie in einer anderen Funktion festlegen kann, dass erst wenn alle Daten einer bestimmen anderen AJAX-Funktion da sind, weitergemacht wird - z.B. irgendwie über Eventhandler?

Gruß, Christian

  1. Hallo,

    Versuche mal statt

    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");

    nur

      
    ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');  
    
    

    utf-8 ist meines Wissens ohnehin der Default-Mime-Type.

    Dann kannst du statt

    if (ajax.readyState == 4)
         {
             daten = ajax.responseXML.documentElement;
         }

    genauer abfragen:

      
    if (ajax.readyState == 4) {  
      if (ajax.status == 200) {  
        daten = ajax.responseXML.documentElement;  
      } else {  
        alert('Bei dem Request ist ein Problem aufgetreten.');  
      }  
    }  
    
    

    Das ergibt vielleicht eine bessere Eingrenzung des Problems.

    Siehe auch das Tutorial hier.

    Gruß, Don P

  2. Moin Moin!

    Gibt's für sowas keine elegante Lösung, mit der ich irgendwie in einer anderen Funktion festlegen kann, dass erst wenn alle Daten einer bestimmen anderen AJAX-Funktion da sind, weitergemacht wird - z.B. irgendwie über Eventhandler?

    Muß es unbedingt AJAX sein? Wenn Du z.B. dynamisch Javascript nachlädst (per DOM ein Script-Tag in die Seite einbaust), kann das nachgeladene Javascript die gewünschte Funktion aufrufen.

    Das erspart dem Benutzer übrigens auch die frustrierende Meldung, er würde den falschen Browser benutzen.

    Davon abgesehen ist AJAX eine der bookmark-unfreundlichsten Techniken, die mir in letzer Zeit über den Weg gelaufen ist.

    Alexander

  3. Hallo cpw,

    das Problem hast Du doch bereits erkannt. Die Daten sind bei Deinem Zugriff noch nicht verfügbar. Über den Status kannst Du jedoch abfragen, wann sie das sind. Am einfachsten ist es wohl, wenn Du genau dort, den Funktionsaufruf realisierst:

      
    ajax.onreadystatechange = function() {  
       if(ajax.readyState == 4) {  
          daten = ajax.responseXML.documentElement;  
      
          zeigMirDieDaten();  
       }  
    };  
      
    ajax.open('POST', 'daten.xml', true);  
    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");  
    
    

    Du integrierst also den Aufruf in der Handlermethode selbst, die dann die nächste Funktion (inkl. der Daten) anschupsen kann.

    Mit freundlichem Gruß
    Micha

    1. ajax.onreadystatechange = function() {
         if(ajax.readyState == 4) {
            daten = ajax.responseXML.documentElement;

      zeigMirDieDaten();
         }
      };

      Args... ich glaube ich arbeite zuviel ;-) Klar, die Funktion erst in der "ReadyState-Funktion" aufrufen liegt nah. Vielen Dank für den Tip!

      Muß es unbedingt AJAX sein?

      Ja. Ich brauche einen Datei- bzw. Datenbankzugriff über PHP, ohne die Seite neu zu laden - das wird ohne AJAX nicht funktionieren.

      Das erspart dem Benutzer übrigens auch die frustrierende Meldung, er würde den falschen Browser benutzen.

      Wenn er diese frustrierende Meldung bekommt, hat er auch allen Grund frustriert zu sein :-) AJAX wird seit ich-weiß-nicht-wann allgemein unterstützt, der IE kann das z.B. mindestens seit Version 5.5 (ich glaube sogar ab 5.0, kann ich nur leider nicht ausprobieren, da sich diese Version bei mir im MultipleIE ständig aufhängt), und schon bei Windows 2000 (ca. acht Jahre alt...) war der 5.5 serienmäßig dabei. Halbwegs aktuelle Versionen von Firefox, Netscape, Opera, Safari und Konqueror haben auch kein Problem damit.

      Außerdem wären dann auch Google Maps, Map24 und zahlreiche andere auf AJAX basierende Seiten nicht zu verwenden. Super verbleit gibt's an der Tankstelle auch nicht mehr, da wird's halt mal Zeit für ein neues Auto ;-)

      Davon abgesehen ist AJAX eine der bookmark-unfreundlichsten Techniken, die mir in letzer Zeit über den Weg gelaufen ist.

      Das stimmt schon, aber ich möchte mal behaupten, dass es in einer "üblichen" AJAX-Anwendung (wie z.B. Google Maps, einem Fahrzeugkonfigurator oder ähnlichem) auch nicht viel zu bookmarken gibt. Ich baue ja nicht z.B. die Navigation einer Seite oder ähnliches damit.

      utf-8 ist meines Wissens ohnehin der Default-Mime-Type.

      In meinem letzten AJAX-Projekt gab's da z.T. böse Probleme in der AJAX-PHP-MySQL-Kette, darum geb' ich grundsätzlich überall explizit UTF-8 an, sonst schleicht sich in bestimmten Konstellationen irgendwo in der Kette immer noch ISO-8859-1 ein und sorgt für unlesbare Unlaute etc.

      Gruß, Christian

      1. Hallo Christian,

        der IE kann das z.B. mindestens seit Version 5.5 (ich glaube sogar ab 5.0, kann ich nur leider nicht ausprobieren, da sich diese Version bei mir im MultipleIE ständig aufhängt),

        hehe :-)

        und schon bei Windows 2000 (ca. acht Jahre alt...) war der 5.5 serienmäßig dabei.

        Nein, Windows 2000 verfügt standardmäßig über IE 5.0, durch die Servicepacks
        von Windows 2000 aktualisiert sich auch die SP-Version des IE, siehe auch

        </archiv/2005/3/t102851/#m632918> und folgende Postings.

        Freundliche Grüße

        Vinzenz