BlogKontaktTagcloud

Parallel Request mit AJAX und PHP

Das Ausführen von zwei parallelen Requests mit AJAX ist nicht ganz einfach, aber machmal Notwendig. Zu beachten ist das jeder Browser nur eine gewisse Anzahl gleichzeitiger Requests an den gleichen Server ausführen kann.

Ich ging also mutig ans Werk und habe das mal ausgetestet in dem ich einen kleinen Chat implementierte (dazu später mehr). Dazu habe ich das Prototype-Framework verwendet, dessen inoffizielle Dokumentation findet man hier. Eine Request pollt für neue Nachrichten, während ein anderer auf Befehl des Benutzers nachrichten sendet. Irgendwie gingen die Nachrichten nacheinander über den Äther. Ein Schuldiger musste her! Der Schuldige ist bei mir immer im Javascript-Teil zu suchen. Vermutlich setzte das bösse Prototyp-Framework die Request in Serie. Mit dieser Vermutung machte ich auf die Suche in der Doku, im Code (zum Glück nicht so viel Code) und mit FireBug zur Laufzeit.

Und schlussendlich war dann doch nicht der Client schuld. Der "Fehler" steckte im Serverteil und wenn ich mich in PHP nicht so sicher fühlen würde hätte ich vermutlich auch früher die Kommentare in der PHP-Dokumentation gelesen. Da hatte einer zur pre-AJAX Zeit mit Frames ein ziemlich ähnliches Problem. Ich habe beim benchmarken gemerkt das session_start() ewig hängen bleibt.

Der Grund dafür ist einfach und irgendwie logisch, wird eine Session in PHP geöffnet wird sie standardmässig bis zum Abschluss des Seitenaufbaus offen gelassen. Während dieser Zeit ist es nicht möglich die Session erneut zu öffnen, der Aufruf von session_start() blockiert bis die Session vom anderen Request geschlossen wird. Das war auch der Grund warum das Seiten nacheinander abgearbeitet werden.

Die Lösung ist in meinem Fall relativ einfach. In dem lange dauernden Request greife ich nur auf eine einzige Variable lesend zu. Ich lese deshalb nach dem Öffnen der Session die Session-Variable in ein lokale Variable ein und schliesse danach die Session mit session_write_close() gleich wieder. Danach gehts auch mit zwei parallelen Request ohne Probleme und der JavaScript-Teil ist für einmal entlastet!
Ähnliche Beiträge:
Synchroner Aufruf mit XMLHttpRequest in Firefox
Webtuesday: PHP wins!
Webtuesday: PHP vs. Javascript: which sucks more?
Faster google maps with JSON
PHP Quine
Comments (5)  Permalink

"Defekte" for-in-Schleife in JavaScript

"Hunderttausend Höllenhunde" würde Kapitän Haddock wohl zu JavaScript sagen. Ganz werde ich diese Programmiersprache wohl nie verstehen. Man kann mit ihr wunderbare Dinge basteln und ebenso wunderbare Fehler. So geschehen mit meiner neuen Suchmaschine "Loogel".

Ein for-in-Loop über ein assoziatives Array verweigerte im IE seinen Dienst, während das gleiche Konstrukt in einem anständigen Browser ohne Probleme lief. Im Internet gibt es allerlei Erklärungen zu nicht funktionierenden for-in-Schleifen, die hatten aber alle genau gar nichts mit meinem Problem zu tun. Und um es gleich vorweg zu nehmen, der Internet Explorer kann in diesem Fall nicht allzu viel dafür.

Im nachfolgenden das stark vereinfachte Beispiel. Im Firefox läuft das ganze ohne Probleme während im Internet Explorer die vielsagende Meldung "Das Objekt unterstützt diese Eigenschaft oder Methode nicht." erscheint.

<html><head><title>Test</title>
<script type="text/javascript">
function OnLoad(){
var Ausgabe = "";
var obj = new Object();
obj[324] = "adff";
for (Eigenschaft in obj)
Ausgabe = Ausgabe + Eigenschaft+ ": " + obj[Eigenschaft] + "<br>";
document.write("<h1>Eigenschaften des Objekts <i>document<\/i><\/h1>");
document.write(Ausgabe);
}
</script>

</head>
<body onload="OnLoad()">
<div id="Eigenschaft"></div>
</body>
</html>
Das Problem beginnt damit, dass der DIV-Block mit der id "Eigenschaft" automatisch als Variable im Skope zur Verfügung steht. Mit alert(Eigenschaft); vor dem for-Loop erkennt man das hier das Objekt des Div-Blocks (HTMLDivElement) zugewiesen ist. Der Firefox überschreibt nun dieses Objekt einfach, der Internet Explorer hingegen gibt einen Fehler aus. Richtig wäre das ganze mit einem var vor der Eigenschaft.
   for (var Eigenschaft in obj)
Ausgabe = Ausgabe + Eigenschaft+ ": " + obj[Eigenschaft] + "<br>";
Der Div-Block wird danach nicht mehr automatisch der Variablen zugeordnet. alert(Eigenschaft); vor dem for-Loop gibt nun "undefined" zurück. (Was wiederum aus meiner Sicht ein wenig magisch ist.)

Der Sünder ist in diesem Fall jedoch nicht der Internet Explorer. Seine Fehlermeldung ist zwar wenig aussagekräftig, aber durchaus korrekt. Nach ECMA-Standard gibt es zwei for-in-Loops, einen mit var und einen ohne. Bei denjenigen ohne var muss vor dem in eine LeftHandSideExpression stehen, was zum Beispiel ein Feldaufruf, ein Arrayzugriff oder ein Funktionsaufruf sein kann, jedoch kein Objekt wie in meinem Beispiel.
Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
Assoziative Array nach Value sortieren
Synchroner Aufruf mit XMLHttpRequest in Firefox
Webtuesday: PHP wins!
Webtuesday: PHP vs. Javascript: which sucks more?
Comments (4)  Permalink

Assoziative Array nach Value sortieren

Javascript ist in Sachen Datentypen nicht gerade gut ausgestatte. Assoziative Arrays lassen sich nur mit ein wenig würgen hinzaubern. Sortieren nach Value erfordert einen noch grösseren Würg. Sortieren nach Value ist immer dann nötig wenn man ein Assoziative Array zum Zählen von Items verwendet. Das Item wird dann als Key verwendet und im Value wird das Vorkommen gezählt.

Im nachfolgenden Beispiel werden in einem assoziativen Array (allTags) die Tags als Key verwendet und im Value wird das vorkommen des Tags gezählt. Und so gehts:

//Sortier-Funktion, grösster Wert am Anfang
function Numsort (a, b) {
return b - a;
}

//Hilfsvariablen
var valueArray = new Array();
var sortedArray = new Object();

//Alle Values in ein Array speichern
for (var tag in allTags){
valueArray.push( allTags[tag] );
}

//Array mit Sortier-Funktion sortieren
valueArray.sort(Numsort);

//Neues Bucket-Array anlege
for(var i = 0; i<valueArray.length;++i){
sortedArray[ valueArray[i] ] = new Array();
}

//Buckets mit den Tags fühlen
for (var tag in allTags){
sortedArray[ allTags[tag] ].push(tag);
}

//Tags der Reihenfolge nach ausgeben
for (var tags in sortedArray) {
for(var i = 0; i<sortedArray[tags].length;++i) {
tag = sortedArray[tags][i];
alert("Tag \""+tag+"\" kommt "+tags+"mal vor." );
}
}

Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
"Defekte" for-in-Schleife in JavaScript
Synchroner Aufruf mit XMLHttpRequest in Firefox
Webtuesday: PHP wins!
Webtuesday: PHP vs. Javascript: which sucks more?
Comments (0)  Permalink

Synchroner Aufruf mit XMLHttpRequest in Firefox

Ein synchroner XMLHttp-Aufruf in JavaScript ist theoretisch nicht so schwer. Die Dokumentation ist, wohl weil synchrone Aufrufe im Vergleich zu asynchronen relativ selten benötigt werden, eher spärlich und teilweise verwirrend. Das grösste Problem ist dass das XMLHttpRequest-Objekt sind nicht in allen Browsern gleich verhält. So lässt sich der untenstehende Request im Konqueror (und wohl auch in älteren Internet Explorern und Safari) ausführen, obwohl der Aufbau eigentlich falsch ist.

//Not valide Request!
xmlHttp.open('GET', 'json.php?name='+name, false);
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
var resp = eval(xmlHttp.responseText);
saveVar.c = resp['id'];
if(vonNr.c && zuNr.c){
foundIDs();
}
}
};
xmlHttp.send(null);
Diese direkte Umwandlung des asynchronen Request in eine Synchronene ist nicht zulässig und funktioniert deshalb im Firefox (und vermutlich in anderen Browser die den Mozilla-Kern verwenden) nicht. Der korrekte asynchrone Aufruf sieht wie folgt aus:

xmlHttp.open('GET', 'json.php?name='+name, false);
xmlHttp.send(null);

var resp = eval(xmlHttp.responseText);
saveVar.c = resp['id'];
if(vonNr.c && zuNr.c){
foundIDs();
}
Wobei in diesem Fall die Methode send blockierend ist und auf die Antwort vom Server wartet. Der nachfolgende Code wird erst nach dem send eine Antwort erhalten hat ausgeführt.
Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
Faster google maps with JSON
Web-Continuations - Technolgie 2007
"Defekte" for-in-Schleife in JavaScript
Assoziative Array nach Value sortieren
Comments (2)  Permalink

Webtuesday: PHP wins!

Die beiden Kontrahenten beim gestrigen "Kampf" JavaScript vs. PHP zeigten sich recht angriffslustig. So wurde relativ häufig geflucht, die andere Sprache mit Vorwürfen eingedeckt und nicht davor gescheut Nachteile der eigenen Sprache einfach unter den Tisch zu kehren oder weg zu diskutieren. Es zeigte sich jedoch wenn man zwei Sprachen gegeneinander antreten lässt, man schnell Features vergleicht die nur Personen kennen die sich täglich mit diesen Sprachen auseinandersetzten. Der Fight war hitzig und ausserordentlich amüsant. Am Schluss gewann Maarten mit PHP, zum grossen Erstaunen aller, vor JavaScript.

Folien, Wahl-Resultate und Wahlmaschine (im neutralen Perl) sind bereits auf dem Webtuesday-Wiki zu finden. Mehr auf Harry's Blog.
Ähnliche Beiträge:
Webtuesday: PHP vs. Javascript: which sucks more?
Parallel Request mit AJAX und PHP
Webtuesday
PHP Quine
What's php like?
Comments (4)  Permalink

Webtuesday: PHP vs. Javascript: which sucks more?

Es scheint zur Gewohnheit zu werden das am Webtuesday Äpfel mit Birnen verglichen werden. Diesmal werden Maarten für PHP und Harry für JavaScript in den Ring steigen ("both of us shamelessly advocating each language"--Harry).

Harry hofft auf "an entertaing language / flamewar in real time - bring your rotten tomatoes and custard pies for throwing." Ich werde heute Abend dort sein, nicht mit grosser Sympatie für die einte oder andere Sprache, wohl aber mit dem üblich unguten Gefühl wenn ich JavaScript-Code sehe.

Mehr auf der Webtuesday-Seite.

[via chregu]
Ähnliche Beiträge:
Webtuesday: PHP wins!
Parallel Request mit AJAX und PHP
Webtuesday
PHP Quine
What's php like?
Comments (0)  Permalink

Faster google maps with JSON

Vor einiger Zeit habe ich mit Google Maps eine einfache Karte erstellt mit welcher Webseiten, die bei Geourl gelistet sind, angezeigt werden können. Heute habe ich nun, inspiriert durch einen Artikel, eine weitere Karte die mit JSON läuft zusammengebastelt.

JSON ist ein Subset von JavaScript welches für den Austausch von Daten definiert wurde, somit also quasi eine Art DTO erzeugt. Das Tolle dabei ist das ein übertragener JSON Text direkt mit "eval" in JavaScript als Objekt-Struktur geladen werden kann und so kein zusätzliches Parsing benötigt und die übertragenen Daten relativ kompakt sind.

Der Nachteil ist das auf der Serverseite, in diesem konkreten Fall, einiges mehr erledigt werden muss. Bisher reichte es den Rss-Stream von Geourl mit "readfile" durchzuschleifen und die übergebenen Parameter aus Sicherheitsgründen kurz zu überprüfen.

Nun muss das RSS-File auf dem Server geparst werden (geschieht in meinem Fall mit der netten Magpie RSS Bibliothek) und zu einer JSON-Struktur umgebaut werden bevor es an den Client ausgeliefert werden kann. Dieser kann dann das ausgelieferte File, wie schon erwähnt, nur noch mit "eval" laden.

Der direkte Vergleich der alten Lösung mit der neuen JSON-Lösung zeigt das die neue Lösung schneller ist. Wieviel schneller lässt sich aber wegen der relativ ungenauen Messung leider nicht sagen. In der, bei beiden Lösungen, nun angegebenen "parse time" ist nur das Clientseitige Parsen, respektive Laden, und erzeugen der Markierungen angegeben.

Für andere Projekte können auch andere im "Ajax serialization"-Artikel erwähnte Technologien interessant sein. Für klassische Webseiten ist AHAH vermutlich in vielen Fällen ausreichend.
Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
Synchroner Aufruf mit XMLHttpRequest in Firefox
Loogel findet mehr
Web-Continuations - Technolgie 2007
"Defekte" for-in-Schleife in JavaScript
Comments (1)  Permalink

Server Side Javascript

Totgesagte leben länger! Ganz speziell in der IT. Vor einem halben Jahr haben wir in der Vorlesung Internettechnologien "Server Side Javascript" kurzerhand für tot erklährt.

Selbstverständlich ist "Server Side Javascript" nicht tot. Wie lebend das ganze ist habe ich letztlich beim surfen im Internet entdeckt. Sowohl die Blogcommunity twoday, als auch antville setzen auf ein Framework Namens Helma auf, welches Javascript auf den Server bringt.

Zu twoday gibts sogar Zahlen. Knallgrau, die Betreiber von twoday, haben auf ihrem Weblog einige Kennzahlen aus ihren Logs veröffentlicht. Mit zwei Servern werden täglich 65'000 Besucher bedient die zusammen 300'000 Page Impressions erzeugen. Pro Monat zählen sie 4,5 Mio. RSS-Zugriffe. Beeindruckend, nicht?

Helma scheint ein recht intressantes Projekt zu sein, schade das ich nicht mehr Zeit habe und mal einen Blick darauf werfen kann.
Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
"Defekte" for-in-Schleife in JavaScript
Assoziative Array nach Value sortieren
Synchroner Aufruf mit XMLHttpRequest in Firefox
Webtuesday: PHP wins!
Comments (0)  Permalink

Google Map zeigt Webseiten-Koordinaten an

Von der Idee die Position von Webseiten auf einer Karte anzuzeigen lassen war ich schon immer sehr begeistert. In letzter Zeit gab es immer wieder Versuche Karten und Positionen von Webseiten zu verbinden. Chregu hat einen Versuch gestartet die geourl Daten schweizer Blogs mit einer Karte zu verbinden und Matthias ist nachgezogen. Das sind nur zwei Beispiele der Verbindung von Geourldaten mit Karten. Beide kämpfen aber damit das sie kein freizügängliches Karten oder Satelliten Material in guter Qualität bekommen.

Da mich das ganze recht intressiert habe ich mir vorgenommen in den Semesterferien auch so was zu machen. Als ich dann bei Heise lass das Google ein kostenloses API für ihre Map erstellt hat war der Entschluss klar das ich's mal damit versuchen möchte. Gleichzeitig konnte ich mich mal mit JavaScript ein bischen üben.

JavaScript verhält sich teilweise recht merkwürdig und ist ein bischen komisch zu programmieren. Das API von Google ist aber eine coole Sache und sehr mächtig. Meine "Applikation" ist eigentlich fast vollständig in JavaScript programmiert, einzig eine kleine Umleitung der Daten von GeoURL über meinen Server, das ist wegen den Sicherheitseinstellungen der Browser nötig, würde in PHP (5-Zeiler oder so) programmiert. Das ganze Projekt ist mehr als Technologie-Studie denn als Produkt zu verstehen. Das ganze fühlt sich vieleicht ein wenig unfertig an und ist es auch. Trotzdem wenn's intressiert, hier ist der Link dazu.

Dinge die ich mal noch machen könnte währen eine asynchrone, wartende Template Klasse die den for-loop ersetzt und somit keine Timeouts mehr erzeugen würde. Auserdem müsste man mal berechnen wieviele Punkte von Geourl übertragen werden müssen (für die Grösse der Karte) und wenn man das ganze Serverseitig cachen könnte, damit nicht immer alle Punkte neu berechnet werden müssten, währe das natürlich auch tool. Eventuell könnte man dabei die Punkte auch gleich in einem weniger parserintensiven XML Format oder gar als CVS-Datei übertragen. Die Zeit und Lust wird allerdings vermutlich nur mal noch für den ersten Punkt reichen.

Ach PS damit hätten wir im überigen auch geklährt wo der Mittelpunkt des Planeten ist (ähh, nein doch erst dieses Planeten).
Ähnliche Beiträge:
Parallel Request mit AJAX und PHP
"Defekte" for-in-Schleife in JavaScript
Assoziative Array nach Value sortieren
Synchroner Aufruf mit XMLHttpRequest in Firefox
Webtuesday: PHP wins!
Comments (1)  Permalink
1-9/9