Permafrost: Ajax: return() Problem

hallo
ich bin am Ajax lernen, habe einen Kurs besucht und experimentiere nun mit Scripten aus dem Kurs.

hier im Bsp. habe ich eine fkt. "schreib()", welche 3 parameter bekommt und wiederum eine fkt. "ajax()" aufruft, welche einen Ajax Request absetzt. Es wird der Inhalt der txt datei "21_hallowelt.txt" geholt und ausgegeben. Es steht dort nur "Hallo Welt" drinnen.

Ich möchte meine scripte möglichst universell halten, deswegen kann ich es nicht leiden, wenn in der Fkt. die die Ajaxinstanzen aufruft, die Ergebnisse direkt verarbeitet werden (wie im Kurs-Beispiel).
Ursprünglich wurde das <div> mit der ID "hallo" direkt in Zeile 44 mit dem Ergebnis von req.responseText beschrieben- das hat funtionier. Wie gesagt das möchte ich vermeiden und den Wert lieber über'n  return() zurückgeben. in Zeile 11 werden die nötigen Parameter auch korrekt übernommen. Egal ob ich meinen return() in zeile 45 oder 45 schreibe, er gibt jedesmal "undefined" zurück. Der alert() in Zeile 44 gibt aber korrekt "Hallo Welt" aus!

Zum besseren Zeilenfinden hab ich den Code nochmal hier:
http://paste.ubuntuusers.de/392404/

hier das funktionierende Kursbeispiel:
http://paste.ubuntuusers.de/392406/

Was mach ich falsch? danke.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtm1/DTD/xhtml-transitional.dtd" >  
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" >  
<head>  
 <title>Ajax: erste Ajax applikation </title>  
</head>  
<body>  
 <script type="text/javascript">  
 //<![CDATA [  
 var result;  
  
 function schreib(meth,ressource,sync)  
 {  
 var d = document.getElementById("hallo"); //  DOM Befehl  
 d.innerHTML = ajax(meth,ressource,sync);  
 }  
  
 function ajax(meth,ressource,sync)  
 {  
  var r;  
  var req = (window.XMLHttpRequest)  
  ?  
  new XMLHttpRequest() // für Gecko  
  :  
   ((window.ActiveXObject)  
     ?  
     new ActiveXObject("Microsoft.XMLHTTP")  // für IE  
     :  
     false  
     );  
  
  // Request :  open( methode, URL, true bei asynchron false bei synchron)  
  req.open(meth,ressource,sync)  
  
  // Zustand der Verbindung  
  req.onreadystatechange = function()  
  {  
   //Anfrage erfolgreich  
   if (req.readyState == 4)  // loadet, fertiggeladen siehe bei "Properties"  
   {  
    // Status der Antwort  
    if (req.status == 200)  
    {  
     r = req.responseText;  // obj. d wird mit resonseText beschrieben  
     alert(r);  
     return(r);  
     //  
    }  
   }  
  }  
  // return(r);  
  // Verbindung beenden  
  req.send(null);  
 }  
 // ]]>  
 </script>  
  
<body onload="schreib('GET','21_hallo.txt',true);">  
 <div id="hallo"></div>  
</body>  
</html>
  1. Hi,

    Ich möchte meine scripte möglichst universell halten, deswegen kann ich es nicht leiden, wenn in der Fkt. die die Ajaxinstanzen aufruft, die Ergebnisse direkt verarbeitet werden (wie im Kurs-Beispiel).
    Ursprünglich wurde das <div> mit der ID "hallo" direkt in Zeile 44 mit dem Ergebnis von req.responseText beschrieben- das hat funtionier. Wie gesagt das möchte ich vermeiden und den Wert lieber über'n  return() zurückgeben. in Zeile 11 werden die nötigen Parameter auch korrekt übernommen. Egal ob ich meinen return() in zeile 45 oder 45 schreibe, er gibt jedesmal "undefined" zurück. Der alert() in Zeile 44 gibt aber korrekt "Hallo Welt" aus!

    Bedingt durch die asynchrone Arbeitsweise von AJAX wird die Funktion, die du als readyState-Handler angibst, nicht "direkt" aufgerufen, sondern aus dem aktuellen Ausfuehrungskontext herausgeloest. Dementsprechend hat diese gar keine "Stelle", an die sie per return Daten zurueckgeben koennte.

    Wenn du also nicht auf synchrone Abarbeitung umsteigen moechtest (das ist generell keine gute Idee, weil es die restliche Scriptabarbeitung auf der Seite blockieren kann) - dann ueberlege dir, wo du den Wert "zwischenspeichern" kannst, und wie du danach eine weitere Funktion aufrufst, die etwas mit dem Wert anfaengt.

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
  2. Ursprünglich wurde das <div> mit der ID "hallo" direkt in Zeile 44 mit dem Ergebnis von req.responseText beschrieben- das hat funtionier. Wie gesagt das möchte ich vermeiden und den Wert lieber über'n  return() zurückgeben.

    Wie gesagt arbeitet XMLHttpRequest sinnigerweise asynchron. Man arbeitet daher nicht mit Rückgabewerten, sondern mit sogenannten Callback-Funktionen. Das heißt, man übergibt eine Funktion, die aufgerufen wird, wenn die Serverantwort eingetroffen ist und die Daten zur Verfügung stehen.

    function ajax(meth,ressource,sync)

    function ajax (meth, ressource, callback)

    {
      var r;
      var req = (window.XMLHttpRequest)
      ?
      new XMLHttpRequest() // für Gecko
      :
       ((window.ActiveXObject)
         ?
         new ActiveXObject("Microsoft.XMLHTTP")  // für IE
         :
         false
         );

    // Request :  open( methode, URL, true bei asynchron false bei synchron)
      req.open(meth,ressource,sync)

    // Zustand der Verbindung
      req.onreadystatechange = function()
      {
       //Anfrage erfolgreich
       if (req.readyState == 4)  // loadet, fertiggeladen siehe bei "Properties"
       {
        // Status der Antwort
        if (req.status == 200)
        {

    callback(req.responseText, req);

    }
       }
      }

    req.send(null);
    }

    <body onload="schreib('GET','21_hallo.txt',true);">

    Stattdessen übergibst du schreib eine Funktion als dritten Parameter:

    window.onload = function () {
       schreib('GET', '21_hallo.txt', function (response) {
          document.getElementById("hallo").innerHTML = response;
       })
    };

    Diese Funktion erhält den responseText als ersten Parameter und verwendet ihn.

    Vielleicht kennst du diese Schreibweise von Funktionen noch nicht, es handelt sich um sogenannte Funktionsausdrücke. So kannst du Funktionen einfach notieren (= Funktionsobjekte erzeugen) und diese z.B. einer anderen Funktion direkt als Parameter übergeben.

    Mathias

    1. Danke erstmal für beide Antworten. hat funktioniert mit dem callback! siehe hier (in diesem pasteservice sieht der Code schöner aus IMO):
      http://paste.ubuntuusers.de/392408/

      Zeile# 10: Als vierten Parameter habe ich noch die sync-eigenschaft ('true') mit angegeben. eigentlich unnötig, aber der Vollständigkeit halber.
      In Zeile# 25 wird sie dann verwendet. die Funktion "schreib()" fiel gleich ganz weg.

      "Callback" war tatsächlich nicht Bestandteil des Ajaxkurses. Damit werde ich nun hoffentlich unabhängigere, wieder verwendbare Ajax scripte schreiben können die auch den Fachmann überzeugen werden :)

      Vielen Dank.

      1. Alternativ könntest du natürlich der Funktion »schreib« die ID des Elementes geben, in die der abgerufene Inhalt geschrieben werden soll. Aber mit einem Callback hast du natürlich vielfältigere Anpassmöglichkeiten. Dann würde ich die Funktion aber nicht so spezifisch »schreib« nennen.

        "Callback" war tatsächlich nicht Bestandteil des Ajaxkurses.

        Hehe. Unzählige Operationen in JavaScript laufen Event- und Handlerbasiert. Wenn in einem Ajax-Kurs nicht von dieser Asynchronität die Rede ist, die man quasi überall antreffen kann, solltest du vielleicht dein Geld zurück verlangen...

        Mathias