Apr 04
JavaScript / AJAX: Callbacks umgehen, Verkettung von Befehlen
Ich beschäftige mich zur Zeit intensiv mit JavaScript, da es mir clientseitig einige Arbeit abnehmen soll.
Beispiel: JavaScript Templateparser
Ich stehe immer noch zu OOP und auch JavaScript untersützt OOP hochgradig, allerdings in einer für PHPler ungewohnten Form: mit Prototypes, ohne Klassen. Überhaupt ist in JavaScript alles ein Objekt oder – noch besser – eine Funktion! Ich habe hier keine Zeit eine JavaScript Einführung zu geben, ich bitte daher um selbständige Fortbildung um diesen Artikel verstehen zu können.
AJAX Requests sind asynchron, laufen also immer mit Callbacks. Ich verwende jQuery als JS-Framework.
$.get(url, function(data) { // callback code });
Wenn ich nun mehrere Requests brauche, weil ich – im Falle des Templateparsers – Template, Sprache und Daten brauche, dann gibt das eine häßliche Verschachtelung:
$.get(tplurl, function(tpl) { // hole Template $.get(lngurl, function(lng) { // hole Sprache $.get(url, function(data) { // hole Daten $.bindTo(tpl, data, lng, '#content'); // parse das Template mit den Daten und der Sprache nach #content }); }); });
Und das ist noch vereinfacht… Dabei hätte ich viel lieber, wobei die Templates und die Sprache gecacht werden sollen:
$.get(url, function(data) { $tpl(tplID).bindTo(data, lngID, '#content'); });
Nun.. wie bekommen wir das Callback weg?
Analyse des Problems:
Wir wollen anstatt eines Callbacks eine Verkettung per Punktschreibweise (Objektmethodenaufrufe), das bedeutet die Befehle die auf das Templateobjekt ausgeführt werden, werden höchstwahrscheinlich AJAX Requests beinhalten, auch wenn der Cache verwendet werden kann, müssen wir innerhalb mit Callbacks arbeiten, aber wir können sie nach außen hin verstecken, solange dem Coder gewahr ist, dass der bindTo-Aufruf auch asynchron ist. Für den Fall, dass man doch weiter abhängigen Code hat, führt kein Weg an weiteren Callbacks vorbei.
$tpl(tplID, callback).bindTo(data, params{lang,callback…})
Trotzdem wird das Aussehen komprimiert und etwas lese- und schreibfreundlicher.
Nun, wie ist das im Inneren gelöst?
Wir definieren zuerst eine Funktion get() (private), die das Template auftreibt, sei es aus dem Cache oder per Request. In beiden Fällen führt sie (oder der zugehörige Request) das interne Callback aus, sofern es gesetzt ist.
Das Objekt besitzt nun die public Methode bindTo, welche zuerst das interne Callback definiert (mit dem echten internen bindTo Code) und dann get() aufruft. Dazu kommen noch die beiden äußeren Callbacks von $tpl und bindTo, die wie das interne Callback am Ende von get() aufgerufen werden, sofern sie definiert sind.
Folge: Beim Aufruf von $tpl(tplID) passiert noch nichts besonderes, außer das ein Objekt zu Rückgabe gebildet wird. Der Aufruf von bindTo() auf dem Objekt stößt nun den Request an, welcher danach das echte bindTo ausführt!
So. Das wollte ich loswerden :D, vielleicht hilft es ja irgendwem oder animiert Leute JavaScript zu lernen…
Bei echtem Verwendungsinteresse des Codes einfach Mail an mich.
Oktober 2nd, 2009 at 16:36
Kompetenter Blogeintrag, finde PHP an sich aber trotzdem einfacher als JavaScript und Ajax … 😛
OOP ist auf jeden Fall ne feine Sache, zumal in vielen Programmiersprachen eingesetzt.