Callback-Funktion für die Ajax-Klasse

Nun gibts wieder ein kleines Update meiner Ajax Klasse. Das "Problem" an der alten Version war, dass die Ausgabe einfach in ein HTML-Element geschrieben wurde. Dies ist natürlich eine Einschränkung, auch wenn es bei meinen Scripten zu 95% korrekt ist. Bei den anderen 5% muss die Ausgabe der Daten aber anders aussehen. Bisher war die folgende Zeile für die Ausgabe verantwortlich:
document.getElementById(obj.dst).innerHTML=http.responseText;

Die Lösung ist nun die Folgende: Man kann der Klasse wenn nötig eine Funktion mit dem Namen "response" hinzufügen und wenn die existiert wird sie mit den Daten als Parameter aufgerufen, sonst werden die Daten wie bisher einfach ins HTML-Element geschrieben. Aus der Zeile oben wird nun der folgende Codeschnippsel:
// wenn obj.response eine funktion ist, diese aufrufen
if(typeof(obj.response)=="function")
{
    obj.response(http.responseText);
}
else
{
    // antwort ins html element schreiben
    document.getElementById(obj.dst).innerHTML=http.responseText;
}

Und die Benutzerdefinierte "Callback-Funktion" erstellt man so:
ajax=new XMLHttp;

// benutzerdefinierte funktion
ajax.response=function(response)
{
    // inhalt ins html element schreiben
    document.getElementById(ajax.dst).innerHTML=response;

    // element mit einem scriptaculous effekt anzeigen
    Effect.BlindDown(ajax.dst);
}

// ajax request starten
ajax.start("rpc.php?id="+id,"element");

Das wars auch schon. Recht simpel aber es Funktioniert tadellos und ist in meiner Meinung auch sehr einfach zu handhaben. Die komplette Klasse sieht nun so aus:
// Objekt XMLHttp
// Param url: Url der aufzurufenden Datei
// Param dst: ID des HTML-Elements
XMLHttp=function()
{
    // Den Browsertyp auslesen
    var browser=navigator.appName;
    var obj=this;

    if(browser=="Microsoft Internet Explorer")             // IE
    {
        var http=new ActiveXObject("Microsoft.XMLHTTP");
    }
    else                                                   // Mozilla, Safari, Opera, usw.
    {
        var http=new XMLHttpRequest();
    }
    
    obj.start=function(url,dst,load)
    {
        http.abort();
        obj.dst=dst;

        // HTTP-Request senden
        // Parameter url als Adresse
        http.open("GET",url,true);

        // Wenn Status geaendert wurde
        http.onreadystatechange=function()
        {
            // ueberpruefen, ob daten gesendet wurden
            // readystate 4 = complete
            if(http.readyState==4)
            {
                // ueberpruefen, ob status vom server richtig ist
                // status 200 = OK
                if(http.status==200)
                {
                    // wenn obj.response eine funktion ist, diese aufrufen
                    if(typeof(obj.response)=="function")
                    {
                        obj.response(http.responseText);
                    }
                    else
                    {
                        // antwort ins html element schreiben
                        document.getElementById(obj.dst).innerHTML=http.responseText;
                    }
                }
                else if(http.status!=0)
                {
                    // HTTP Fehlercode zurückgeben
                    document.getElementById(obj.dst).innerHTML="Fehler:\nHTTP-Status: "+http.status+"\nHTTP-Statustext: "+http.statusText;
                }
            }
        }
        
        http.send(null);
    }
}

Update der Ajax-Klasse

Nun habe ich doch noch einen "Fehler" in meiner Ajax-Klasse gefunden. In meiner Web-Applikation kann der Benutzer in mehreren Inputfeldern Daten Filtern, die dann in einem Dix-Container ausgegeben werden. Mit einem listener auf den Felder wird überprüft, ob etwas eingegeben wurde und sobald dies der Fall ist, wird mittels Ajax die PHP-Datei aufgerufen und die Daten in den Container geschrieben. Soweit so gut, das hat mit der alte Klasse auch recht gut geklappt. Allerdings ist es ja so, dass je mehr Daten der Benutzer eingab, desto weniger Daten musste die PHP-Datei zurückgeben. Mehr Filterdaten=Weniger Daten.
Das bedeutet aber auch, dass die Requests die anfangs gestartet werden länger dauern als die die später gestartet werden. Nun kann es also sein (wenn der Benutzer schnell ist), dass zuerst ein Request gestartet wird, bei welchem eine grosse Datenmenge zurück kommt. In der Zwischenzeit wird ein nächster Request, vom selben Benutzer in derselben Session ein neuer Request mit mehr Filter-Daten gestartet, bei welchem weniger Daten zurückkommen. Dieser wird natürlich von PHP schneller abgearbeitet und wird auch schneller zum Browser übertragen. So werden diese Daten schön im Div-Container angezeigt. Soweit so gut, das Problem ist nun allerdings, dass noch der andere Request mit der grösseren Datenmenge läuft und sobald der fertig ist, werden die Daten angezeigt. Also die alten, die der Benutzer gar nicht sehen will.
Das bedeutet nun also, dass sobald ein neuer Request gestartet wird, der alte, noch laufende, abgebrochen werden soll. Allerdings sollen aber trotzdem mehre Requests paralell laufen können.

Das bedeutet, dass pro Objekt ein Request aufs mal laufen soll, aber man soll mehrere Objekte erstellen können, die dann paralell laufen können.

In meiner Lösung erstellt man nun als erstes eine Referenz zu einem Objekt in welchem ein XMLHttp Objekt erstellt wird. Wenn nun ein Request gestartet werden soll, ruft man die Methode start() mit URL, und ID des Ziels auf. Sobald ein neuer Request mit demselben Objekt gestartet wird, wird der alte abgebrochen.
ajax=new XMLHttp;
ajax.start("ajax.php?param=test","feld");
Weitere Requests können dann so gestartet werden:
ajax.start("ajax.php?param=blub","feld");
Und auch mehrere paralelle Requests sind kein Problem:
ajax1=new XMLHttp;
ajax2=XMLHttp;

ajax1.start("ajax.php?param=ajax1","feld1");
ajax2.start("ajax.php?param=ajax2","feld2");
Und die ganze Klasse sieht dann so aus:
// Objekt XMLHttp
// Param url: Url der aufzurufenden Datei
// Param dst: ID des HTML-Elements
XMLHttp=function()
{
    // Den Browsertyp auslesen
    var browser=navigator.appName;
    var obj=this;

    if(browser=="Microsoft Internet Explorer")             // IE
    {
        var http=new ActiveXObject("Microsoft.XMLHTTP");
    }
    else                                                   // Mozilla, Safari, Opera, usw.
    {
        var http=new XMLHttpRequest();
    }

    obj.start=function(url,dst)
    {
        // bereits laufende requests abbrechen
        http.abort();

        obj.dst=dst;

        // HTTP-Request senden
        // Parameter url als Adresse
        http.open("GET",url,true);

        // Wenn Status geaendert wurde
        http.onreadystatechange=function()
        {
            // ueberpruefen, ob daten gesendet wurden
            // readystate 4 = complete
            if(http.readyState==4)
            {
                // ueberpruefen, ob status vom server richtig ist
                // status 200 = OK
                if(http.status==200)
                {
                    // Antwort vom Server in HTML-Element schreiben
                    // dst als ID
                    document.getElementById(obj.dst).innerHTML=http.responseText;
                }
                else if(http.status!=0)
                {
                    // HTTP Fehlercode zurückgeben
                    document.getElementById(obj.dst).innerHTML="Fehler:\nHTTP-Status: "+http.status+"\nHTTP-Statustext: "+http.statusText;
                }
            }
        }

        http.send(null);
    }
}

Simple AJAX-Klasse

Ich habe vor ca zwei Jahren bereits einen kleinen Beitrag über Ajax geschrieben und muss das nun für ein Projekt im Geschäft neu aufrollen. Mit etwas OOP habe ich eine Ajax-Klasse geschrieben, die die Daten vom Server abholt und in ein beliebiges HTML-Element einfügt.
Mit dieser Klasse sind auch mehrere paralelle Anfragen möglich und das ganze funktioniert im Firefox, IE und Opera. Andere Browser habe ich (noch) nicht getestet. Die Klasse erwartet den Parameter Url (die Adresse die aufgerufen werden soll) und Dst (die ID des HTML-Elements für die Ausgabe). Mit einigen Veränderungen kann die Klasse die Daten vom Server auch anderst ausgeben und natürlich kann man das noch beliebig erweitert (Lade-Bilder usw.).
// Objekt XMLHttp
// Param url: Url der aufzurufenden Datei
// Param dst: ID des HTML-Elements
XMLHttp=function(url,dst)
{
    // Den Browsertyp auslesen
    var browser=navigator.appName;

    if(browser=="Microsoft Internet Explorer")             // IE
    {
        var http=new ActiveXObject("Microsoft.XMLHTTP");
    }
    else                                                   // Mozilla, Safari, Opera, usw.
    {
        var http=new XMLHttpRequest();
    }

    // HTTP-Request senden
    // Parameter url als Adresse
    http.open("GET",url,true);

    // Wenn Status geaendert wurde
    http.onreadystatechange=function()
    {
        // ueberpruefen, ob daten gesendet wurden
        // readystate 4 = complete
        if(http.readyState==4)
        {
            // ueberpruefen, ob status vom server richtig ist
            // status 200 = OK
            if(http.status==200)
            {
                // Antwort vom Server in HTML-Element schreiben
                // dst als ID
                document.getElementById(dst).innerHTML=http.responseText;
            }
            else
            {
                // HTTP Fehlercode zurückgeben
                alert("Fehler:\nHTTP-Status: "+http.status+"\nHTTP-Statustext: "+http.statusText);
            }
        }
    }
    http.send(null);
}


Das ganze wird nun folgendermassen aufgerufen. Hier wird die Adresse ajax.php?param=test angefragt und die Anwort vom Server wird in das HTML-Element (div/span/p/usw..) geschrieben.
ajaxObj=new XMLHttp("ajax.php?param=test","feld");