Enrico: Problem mit Ajax-Anfrage

Hallo,

ich habe Probleme mit dem Auslesen einer Ajax-Anfrage, die ich wie folgt aufrufe:

  
xmlhttp = createXMLHTTPObject();  
  
if (xmlhttp != false)  
   sendRequest2 (xmlhttp, "Newsletter.php?Anmeldedaten=" + Anmeldedaten, handleRequest2);  
else  
   alert("Fehler beim Einrichten des xmlhttp-Objekts");  

Die Variable "Anmeldedaten" hat hier einen Wert, das habe ich vorher mit einem alert-Befehl geprüft.

Die zugehörigen Funktionen sehen folgermaßen aus:

  
function createXMLHTTPObject()  
{  
   var a = [function () {return new ActiveXObject("Msxml2.XMLHTTP.6.0");},  
            function () {return new ActiveXObject("Msxml2.XMLHTTP.5.0");},  
            function () {return new ActiveXObject("Msxml2.XMLHTTP.4.0");},  
            function () {return new ActiveXObject("Msxml2.XMLHTTP.3.0");},  
            function () {return new ActiveXObject("Msxml2.XMLHTTP");},  
            function () {return new ActiveXObject("Microsoft.XMLHTTP");},  
            function () {return new XMLHttpRequest();},  
            function () {return false;}],  
       b = a.length,  
       c = 0,  
       d;  
  
   for (; c < b; c++)  
   {  
      try  
      {  
         d = a[c]();  
      }  
      catch (e)  
      {  
         continue;  
      }  
  
      break;  
   }  
  
   return d;  
}  
  
function sendRequest2 (a, b, c)  
{  
   a.open("get", b, true);  
  
   a.onreadystatechange = function ()  
   {  
      if (a.readyState == 4)  
      {  
         if (a.status == 200)  
            c(a);  
         else  
            alert('In der Funktion "sendRequest2" ist der Fehler ' + a.status + " aufgetreten");  
      }  
   }  
  
   a.send();  
}  
  
function handleRequest2 (a)  
{  
   var b = a.responseText;  
  
   alert("handleRequest2: " + b);  
}  

Die Newsletter.php hat derzeit folgenden minimalen Aufbau:

  
if (isset ($_GET["Anmeldedaten"]))  
{  
   $Anmeldedaten = $_GET["Anmeldedaten"];  
  
   return "OK";  
}  
else  
   return "Fehler";  

Leider wird mir in der Funktion "handleRequest2" immer nur "handleRequest2:" angezeigt, d.h. ich bekomme hier keinen Rückgabewert.

Woran liegt das?
Was habe ich falsch gemacht?

Vielen Dank für eure Mithilfe!

Gruß,
Enrico

  1. Lieber Enrico,

    function handleRequest2 (a)

    {
       var b = a.responseText;

    alert("handleRequest2: " + b);
    }

    
    > [...]  
    > Leider wird mir in der Funktion "handleRequest2" immer nur "handleRequest2:" angezeigt, d.h. ich bekomme hier keinen Rückgabewert.  
      
    was sagt denn die Fehlerkonsole Deines Browsers dazu? Findet sie etwa, dass a kein XmlHttpRequestObjekt ist?  
      
    Liebe Grüße,  
      
    Felix Riesterer.
    
    -- 
    "Wäre die EU ein Staat, der die Aufnahme in die EU beantragen würde, müsste der Antrag zurückgewiesen werden - aus Mangel an demokratischer Substanz." (Martin Schulz, Präsident des EU-Parlamentes)
    
    1. Hallo Felix,

      was sagt denn die Fehlerkonsole Deines Browsers dazu?

      "Leider" gar nichts, d.h. sie gibt mir keine(n) Fehler aus.

      Ich habe den Tip von 1UnitedPower umgesetzt, dann kommt allerdings der "Fehler: TypeError: a.target is undefined".

      Gruß,
      Enrico

  2. Meine Herren!

    function handleRequest2 (a)
    {
       var b = a.responseText;

    alert("handleRequest2: " + b);
    }

      
    Die Callback-Funktion handleRequest2 wird mit einem AJAX-Event als Parameter aufgerufen. Den Parameter hast du in deiner Funktion mit „a“ benannt. Dann versuchst du die Eigenschaft responseText von diesem Event zu lesen. Diese Eigenschaft gibt es aber für das Event gar nicht. Das ist eine Eigenschaft deiner XMLHttpRequest-Insanz, also in deinem Beispiel von „xmlhttp“. Innerhalb deiner Callback-Funktion kannst du die mit dem Event assoziierte XMLHttpRequest-Instanz über die target-Eigenschaft des Events holen.  
      
    In Quellcode formuliert:  
    `var b = a.target.reponseText;`{:.language-javascript}  
    
    -- 
    “All right, then, I'll go to hell.” – Huck Finn
    
    1. Hallo 1UnitedPower,

      ich habe den Tip von  umgesetzt, dann kommt allerdings der "Fehler: TypeError: a.target is undefined".

      Ich verstehe nicht, warum mein Code nicht funktioniert, da ich, außer der Tatsache, dass nichts zurückgeliefert wird, keine alert-Ausgaben oder Fehler in der Konsole habe.

      Gruß,
      Enrico

  3. ich habe Probleme mit dem Auslesen einer Ajax-Anfrage, die ich wie folgt aufrufe:

    Die Variable "Anmeldedaten" hat hier einen Wert, das habe ich vorher mit einem alert-Befehl geprüft.

    Oh, du benutzt alert()? Dein Browser hat in der Abteilung Entwicklerkrams eine Fehlerkonsole (bzw. sollte er unbedingt haben, wenn du mit HTML, CSS und Javascript arbeitest).

    function handleRequest2 (a)
    {
       var b = a.responseText;

    alert("handleRequest2: " + b);
    }

    Leider wird mir in der Funktion "handleRequest2" immer nur "handleRequest2:" angezeigt, d.h. ich bekomme hier keinen Rückgabewert.

    Informiere dich mal über die Funktion console.log() und verwende sie in handleRequest2() mit deinem Parameter a.

    Eigentlich müsste die Konsole dich, würdest du denn mal reinschauen, aber auch schon ohne console.log(a) auf das Problem aufmerksam gemacht haben.

    1. Hallo Hannes,

      die Konsole liefert mit folgende Werte:

      XMLHttpRequest
      {
         onreadystatechange: sendRequest2/a.onreadystatechange(),
         readyState:         4,
         timeout:            0,
         withCredentials:    false,
         upload:             XMLHttpRequestUpload,
         responseURL:        "http://localhost//Newsletter.php?Anmeldedaten=AAteewK...==",
                             status:       200,
                             statusText:   "OK",
                             responseType: "",
                             response:     ""
      }

      Also ist hier (scheinbar) alles in Ordnung.

      Gruß,
      Enrico

      1. Ich habe jetzt die Newsletter.php um die zu Testzwecken möglichen Situationen und Rückgabewerte ergänzt, aber gleiches Resultat.

          
        if (isset ($_GET["Anmeldedaten"]))  
        {  
           if (!empty ($_GET["Anmeldedaten"]))  
           {  
              $Anmeldedaten = $_GET["Anmeldedaten"];  
          
              return $Anmeldedaten;  
           }  
           else  
              return 'Das Skript "Newsletter" hat einen leeren Wert übermittelt bekommen';  
        }  
        else  
           return "Anmeldedaten wurden nicht korrekt übermittelt";  
        
        

        Die Newsletter.php wird in der Ajax-Anfrage auf jeden Fall gefunden, d.h. es liegt kein Fehler 404 vor.

        Ich verstehe das nicht.

        Die Newsletter.php MUSS etwas zurückliefern und die javascript-Datei somit auch etwas empfangen.

        Gruß,
        Enrico

      2. Lieber Enrico,

        responseURL:        "http://localhost//Newsletter.php?Anmeldedaten=AAteewK...==",

        werden da Daten als base64-enkodierter String übertragen? Das Istgleichzeichen ist ein Sonderzeichen im Query-String! Dieses doppelte Istgleichzeichen sollte URL-kodiert sein, sonst kommen am Server im $_GET- oder $_POST-Array nicht die Werte an, die Du gerne hättest.

        Zum Debuggen gehört natürlich auch, dass Du Dir diese Arrays in eine Textdatei schreiben lässt, um zu "sehen", was da vom Browser tatsächlich ankommt. Probiere es doch einmal damit:

        debug("in _REQUEST steht: ",$_REQUEST,"\r\nin _POST steht: ",$_POST);  
          
        function debug () {  
            $arg_list = func_get_args();  
          
            foreach ($arg_list as $v) {  
          
                if (!is_string($v)) {  
                    $v = print_r($v, true); // true = no immediate output to browser  
                }  
          
                file_put_contents('./debug.txt', $v, FILE_APPEND);  
            }  
        }
        

        Liebe Grüße,

        Felix Riesterer.

        --
        "Wäre die EU ein Staat, der die Aufnahme in die EU beantragen würde, müsste der Antrag zurückgewiesen werden - aus Mangel an demokratischer Substanz." (Martin Schulz, Präsident des EU-Parlamentes)
        1. Hallo Felix,

          oh, das könnte hilfreich sein.

          Ich kann mir das aber leider erst später anschauen, weil ich jetzt weg muss.

          Gruß,
          Enrico

  4. ...ich bei mehreren Ajax-Anfragen an unterschiedlichen Stellen in meinem Javascript das xmlhttp-Objekt immer wieder neu initialisieren muss?

    Könnte es daran liegen?

    Ich habe die komplette URL aus der Windows-Konsole rauskopiert, in die Adresszeile meines Browsers eingefügt und die Newsletter.php direkt aufgerufen, nachdem ich die return-Anweisungen in echo-Befehle geändert habe und dann wurde mir der Inhalt der Variable "Anmeldedaten" korrekt angezeigt.

    Ich dreh noch durch...

    Gruß,
    Enrico

    1. Lieber Enrico,

      ...ich bei mehreren Ajax-Anfragen an unterschiedlichen Stellen in meinem Javascript das xmlhttp-Objekt immer wieder neu initialisieren muss?

      Du wirst verschiedene Instanzen benötigen, ja.

      Hast Du Fälle, in denen mehrere AJAX-Calls parallel verarbeitet werden sollen, also dass die Antwort des einen noch nicht da ist, während der andere schon die nächste Anfrage sendet?

      Liebe Grüße,

      Felix Riesterer.

      --
      "Wäre die EU ein Staat, der die Aufnahme in die EU beantragen würde, müsste der Antrag zurückgewiesen werden - aus Mangel an demokratischer Substanz." (Martin Schulz, Präsident des EU-Parlamentes)
      1. Hallo Felix,

        Hast Du Fälle, in denen mehrere AJAX-Calls parallel verarbeitet werden sollen

        Nein, eine Ajax-Anfrage liest eine Textdatei vom Server ein, eine andere ruft zu einem späteren Zeitpunkt die Newsletter.php auf, d.h. die Anfragen laufen nicht parallel.

        Du meinst also, dass ich bei meiner zweiten Ajax-Anfrage die nachfolgende Funktion noch einmal aufrufen muss?

          
        function createXMLHTTPObject()  
        {  
           var a = [function () {return new ActiveXObject("Msxml2.XMLHTTP.6.0");},  
                    function () {return new ActiveXObject("Msxml2.XMLHTTP.5.0");},  
                    function () {return new ActiveXObject("Msxml2.XMLHTTP.4.0");},  
                    function () {return new ActiveXObject("Msxml2.XMLHTTP.3.0");},  
                    function () {return new ActiveXObject("Msxml2.XMLHTTP");},  
                    function () {return new ActiveXObject("Microsoft.XMLHTTP");},  
                    function () {return new XMLHttpRequest();},  
                    function () {return false;}],  
               b = a.length,  
               c = 0,  
               d;  
          
           for (; c < b; c++)  
           {  
              try  
              {  
                 d = a[c]();  
              }  
              catch (e)  
              {  
                 continue;  
              }  
          
              break;  
           }  
          
           return d;  
        }  
        
        

        Gruß,
        Enrico

        1. Lieber Enrico,

          meiner Erfahrung nach ist es keine gute Idee XmlHttpRequest-Objekte zu recyclen. Jeder Request wird sinnvollerweise mit einem frisch zubreiteten XHR-Objekt abgesandt.

          Liebe Grüße,

          Felix Riesterer.

          --
          "Wäre die EU ein Staat, der die Aufnahme in die EU beantragen würde, müsste der Antrag zurückgewiesen werden - aus Mangel an demokratischer Substanz." (Martin Schulz, Präsident des EU-Parlamentes)
          1. Hallo Felix,

            Jeder Request wird sinnvollerweise mit einem frisch zubreiteten XHR-Objekt abgesandt.

            Wo kann ich nachlesen, wie ich das XHR-Objekt frisch aufbereite?

            Ich steh grad, entschuldige, bitte voll im Wald... ^^

            Gruß,
            Enrico

            1. Hallo Felix,

              Wo kann ich nachlesen, wie ich das XHR-Objekt frisch aufbereite?

                
              Mein neuer Request sieht folgendermaßen aus:  
                
              xmlhttp2 = createXMLHTTPObject();  
                
              if (xmlhttp2 != false)  
                 sendRequest2 ("Newsletter.php?Anmeldedaten=" + Anmeldedaten, handleRequest2);  
              else  
                 alert("Fehler beim Einrichten des xmlhttp-Objekts");  
              
              

              Absenden und auswerten tue ich die neue Anfrage wie folgt:

                
              xmlhttp2.open("get", b, true);  
                
              xmlhttp2.onreadystatechange = function ()  
              {  
                 if (xmlhttp2.readyState == 4)  
                 {  
                    if (xmlhttp2.status == 200)  
                       alert(xmlhttp2.reponseText); // c(a);  
                    else  
                       alert('In der Funktion "sendRequest2" ist der Fehler ' + a.status + " aufgetreten");  
                 }  
              }  
                
              xmlhttp2.send();  
                
              console.log(xmlhttp2);  
              
              

              Gleiches Ergebnis, die PHP-Datei gibt mir einfach nichts zurück oder das Javascript empfängt nichts.

              Gruß,
              Enrico

              1. Gleiches Ergebnis, die PHP-Datei gibt mir einfach nichts zurück oder das Javascript empfängt nichts.

                Zum Empfang im Browser noch der Hinweis auf das Netzwerkprotokoll, das dein Browser ebenfalls führen sollte. Firefox hat es im Menü Entwicklerwerkzeuge unter dem Punkt Netzwerkanalyse, Firebug in seiner Anzeige im Reiter Netzwerk.

                Du bekommst dort die Rohdaten, die der Browser empfängt, also ohne, dass dir da zum Beispiel irgendetwas auch nur annähernd Javascriptiges zwischenfunkt, und kannst so zumindest sicherstellen, dass die Daten, die dein Skript verarbeiten soll, auch zum Skript passen.

                Dein Problem hat allerdings eine andere Ursache:

                if (isset ($_GET["Anmeldedaten"]))
                {
                   $Anmeldedaten = $_GET["Anmeldedaten"];

                return "OK";
                }
                else
                   return "Fehler";

                  
                Rufe dein PHP-Skript mal \_direkt\_ auf und du wirst sehen, dass es nichts ausspuckt: Ausgaben in PHP werden mit echo gemacht, nicht mit return. Vermutlich hast du die obigen Zeilen zum Probieren aus irgendeiner Funktion herausgeholt und die Anpassung vergessen.  
                  
                Tröste dich, vier andere Leute, mich eingeschlossen, haben das auch nicht bemerkt.  
                
                
                1. Hallo Hannes,

                  Ausgaben in PHP werden mit echo gemacht, nicht mit return
                  Tröste dich, vier andere Leute, mich eingeschlossen, haben das auch nicht bemerkt

                  Da bin ich zu sehr später Stunde auch noch drauf gekommen - ein sehr, sehr ärgerlicher Fehler, weil man den sehr leicht übersieht - aber was sagst Du zu dem Ergebnis, dass ich jetzt zwar einen Response bekomme, dieser aber immer nur als "undefined" ausgegeben wird?

                  XMLHttpRequest
                  {
                     onreadystatechange: sendRequest/xmlhttp.onreadystatechange(),
                     readyState: 4,
                     timeout: 0,
                     withCredentials: false,
                     upload: XMLHttpRequestUpload,
                             responseURL: "http://localhost/_____N_E_U_/Newsletter.php?Anmeldedaten=AAYWiQ...iMAO==",
                             status: 200,
                             statusText: "OK",
                             responseType: "",
                             response: "OK"
                  }

                  Gruß,
                  Enrico

                  1. dass ich jetzt zwar einen Response bekomme, dieser aber immer nur als "undefined" ausgegeben wird?

                    XMLHttpRequest
                    {

                    status: 200,
                       statusText: "OK",
                       responseType: "",
                       response: "OK"
                    }

                    Verstehe die Frage jetzt nicht, die Ausgabe sieht doch aus wie erwartet? In welcher Zeile, bei welchem Befehl bekommst du undefined zurück?

  5. Ich würde schauen ob man das noch abkürzen kann. Angenommen du musst wirklich jedes mal alle Objekte durchprobieren bis eins funtioniert, das kostet Zeit. Ob die spürbar ist oder nicht ist vielleicht wieder eine andere Frage, aber sauber ist das mit den vielen Exceptions sicher nicht.
    Man könnte sich beim ersten Versuch merken welches der Objekte funktioniert und dann immer gleich diese eine Objektart erzeugen.

  6. Ich habe noch mal was zusammengehackt. Dein Code sah etwas sehr unübersichtlich aus, das halbe Dutzend Abfragen, wo denn das XMLHttpRequest herkommen möge, "aussagekräftige" Funktionsargumente à la a, b und c, zwei Funktionen, wo eine reichen täte.
    Davon unabhängig solltest du Daten, so es keinen ausdrücklich Grund für GET gibt, immer per POST senden. Das Senden von Daten in der URL (also per GET) hat gravierende Nachteile, die URL ist in Art und Umfang beschränkt, vor allem aber landet eine URL immer in diesem oder jenem Protokoll - das ist mit der letzte Ort, an dem du verantwortungsvollerweise ein Passwort sehen möchtest.

    Im nachfolgenden Skript hast du für die Serveranfrage genau eine Funktion, die du aufrufen musst. Sie erzeugt für jede Anfrage ein eigenständiges XMLHttpRequest-Objekt und bekommt neben der URL ein Objekt, in dem die zu sendenen Daten stehen, und je eine Funktionen, die bei Erfolg bzw. Fehlschlag aufgerufen wird.

    function POST(url, daten, erfolg, fehler)  
    {  
       var r;  
       if (window.XMLHttpRequest) {  
          r = new XMLHttpRequest();  
       }  
       else if (window.ActiveXObject) { // IE <= 8  
          r = new ActiveXObject("Microsoft.XMLHTTP");  
       }  
       if (!r) {  
          return false; // irgendeinen Fehler melden  
       }  
      
       r.open("post", url, true);  
       r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
       r.onreadystatechange = function () {  
          if (r.readyState == 4) {  
             if (r.status == 200) {  
                erfolg(r);  
             }  
             else {  
                fehler(r)  
             }  
          }  
       }  
      
       var p = "";  
       for (k in daten) {  
          p += "&" + encodeURIComponent(k) + "=" + encodeURIComponent(daten[k]);  
       }  
      
       r.send(p);  
    }  
      
    function geht(r)  
    {  
       console.log("Erfolg.", r);  
    }  
      
    function steht(r)  
    {  
       console.log("Ging daneben.", r);  
    }  
      
    // Aufrufen:  
      
    POST("irgendwohin.php", { benutzer: "Hans", passwort: "Franz" }, geht, steht);  
      
    // oder so  
      
    var nutzer = { benutzer: "Hans", passwort: "Franz" };  
    POST("irgendwohin.php", nutzer, geht, steht);  
      
    // oder so  
      
    var nutzer = { benutzer: "Hans", passwort: "Franz" };  
    POST("irgendwohin.php", nutzer, function (r) {  
          console.log("Toll:", r);  
          benutzeristangemeldet();  
          seitetun();  
       },  
       function (r) {  
          console.log("Bockmist.", r);  
       },  
    );  
      
    
    

    Die Daten empfängst du PHP-seitig in $_POST.

    Das Ganze ist sicher noch verbesserungs- und ausbaufähig, sollte aber als Grundlage ausreichen.

    1. Hallo Hannes,

      vielen, vielen lieben Dank für Deine Hilfe und auch für Deine Geduld, dies gilt natürlich auch für Encoder, Felix und 1UnitedPower.

      Ich habe nun ein ähnliches "Framework" gefunden, das wunderbar funktioniert und Deinem ähnlich ist:

        
      var Ajax = {  
         request: function(ops)  
         {  
            if (typeof ops == 'string')  
               ops = {url: ops};  
        
            ops.url = ops.url || '';  
            ops.method = ops.method || 'get'  
            ops.data = ops.data || {};  
        
            var getParams = function (data, url)  
            {  
               var arr = [], str;  
        
               for (var name in data)  
                  arr.push(name + '=' + encodeURIComponent(data[name]));  
        
               str = arr.join ('&');  
        
               if (str != '')  
                  return url ? (url.indexOf('?') < 0 ? '?' + str : '&' + str) : str;  
        
               return '';  
            }  
        
            var api = {  
               host: {},  
               process: function(ops)  
               {  
                  var self = this;  
                  this.xhr = null;  
        
                  if (window.ActiveXObject)  
                     this.xhr = new ActiveXObject('Microsoft.XMLHTTP');  
                  else  
                     if (window.XMLHttpRequest)  
                        this.xhr = new XMLHttpRequest();  
        
                  if (this.xhr)  
                  {  
                     this.xhr.onreadystatechange = function()  
                     {  
                        if (self.xhr.readyState == 4 && self.xhr.status == 200)  
                        {  
                           var result = self.xhr.responseText;  
        
                           if (ops.json === true && typeof JSON != 'undefined')  
                              result = JSON.parse(result);  
        
                           self.doneCallback && self.doneCallback.apply(self.host, [result, self.xhr]);  
                        }  
                        else  
                           if (self.xhr.readyState == 4)  
                              self.failCallback && self.failCallback.apply(self.host, [self.xhr]);  
        
                        self.alwaysCallback && self.alwaysCallback.apply(self.host, [self.xhr]);  
                     }  
                  }  
        
                  if (ops.method == 'get')  
                     this.xhr.open("GET", ops.url + getParams(ops.data, ops.url), true);  
                  else  
                  {  
                     this.xhr.open(ops.method, ops.url, true);  
                     this.setHeaders({'X-Requested-With': 'XMLHttpRequest', 'Content-type': 'application/x-www-form-urlencoded'});  
                  }  
        
                  if (ops.headers && typeof ops.headers == 'object')  
                     this.setHeaders(ops.headers);  
        
                  setTimeout(function()  
                  {  
                     ops.method == 'get' ? self.xhr.send() : self.xhr.send(getParams(ops.data));  
                  }, 20);  
        
                  return this;  
               },  
               done: function(callback)  
               {  
                  this.doneCallback = callback;  
                  return this;  
               },  
               fail: function(callback)  
               {  
                  this.failCallback = callback;  
                  return this;  
               },  
               always: function(callback)  
               {  
                  this.alwaysCallback = callback;  
                  return this;  
               },  
               setHeaders: function(headers)  
               {  
                  for(var name in headers)  
                     this.xhr && this.xhr.setRequestHeader(name, headers[name]);  
               }  
            }  
        
            return api.process(ops);  
         }  
      }  
      
      

      Ich bin mir mittlerweile sicher, dass mein Problem nicht mit der Initierung und Verarbeitung des XHR-Objekts (ich hoffe, ich bringe jetzt keine Fachbegriffe durcheinander) ansich, sondern vielmehr damit zusammenhing, dass Firefox und vielleicht auch IE oder/und Opera Probleme mit hintereinander folgenden Ajax-Abfragen haben, auch wenn diese nicht parallel ablaufen.

      Dass ich "POST" anstelle von "GET" verwenden sollte, klingt aufgrund Deinen genannten Gründen plausibel. Ich werde den gefundenen Code dahingehend noch anpassen und auch verkleiner, so dass automatisch "POST" verwendet wird und ich nicht benötigte Methoden raus werfe.

      Wenn Ajax funktioniert, dann ist es eine tolle Sache. Wenn nicht, dann gestaltet sich die Fehler- bzw. Ursachensuche schwierig, wie ich es am eigenen Leib erleben durfte.

      Gruß,
      Enrico