Javascript: Funktionen Referenz oder Execution

Ein kleiner Ausflug in die Welt der Javascriptprogrammierung. Kurz vorweg, das ist nicht JQuery. Es gibt noch mehr Frameworks und andere Ansätze erlauben auch andere Dinge. Javascript ist da sehr flexibel.

Heute geht es um Funktionsreferenzen. Diese Funktion soll aufgerufen werden :

        function login() {

            var dummy = document.createElement("div");
            if ( dummy.loadURL("cmd/login",$("user").toURI()+"&"+$("pass").toURI()) ) {
                var result = dummy.getValue().trim();
                if ( result == "OK" ) {
                    $("anzeige").loadURL("cmd/listen","");
                } else {
                    $("errormsg").HTML("Leider konnten wir Sie nicht anmelden:
"+ result );
                }
            } else {
                    $("errormsg").HTML("Leider konnten wir Sie nicht anmelden:
"+ result );
            }
        }

Wie man leicht erkennen kann, gibt diese Funktion nichts zurück, soll Sie auch gar nicht.

Dieses kleine Beispiel verwendet die Funktion auf zwei Arten auf:

        window.onload = function() {
             $("anzeige").loadURL("anmelden.html","");
             $("loginbutton").onclick = login();
             $("anmelden").onclick = function(){
                 $("anzeige").loadURL("anmelden.html","");
                 $("loginbutton").onclick = login;
             }
         }

Jetzt raten Sie mal welche Version falsch ist 😉  OK, nicht so schwer. Natürlich ist das richtig:

             $("loginbutton").onclick = login;

Das onlick der Referenzzeiger für die Funktion ist, die beim Click auf das Element ausgeführt werden soll, dürfte bekannt sein, genau  onKeyUp, onKeyDown, onDrag usw. . für andere Events da sind.

Beim Klick auf das LoginButton soll also der Login erfolgen. Wenn man nun aber statt login login() schreibt,  dann wird die Funktion login gleich ausgeführt. Was zur Folge hat, daß obigen Code eine Webseite lädt und in ein Element schreibt, feststellt, daß es nicht ging und eine Errormeldung ausgibt. Der Klick auf das Loginbutton führt dann bestenfalls zu gar nichts, schlimmstenfalls zu einem Crash des Javascriptinterpreter, das kommt auf die Güte des Interpreters an. Kurz um, es passiert nicht was man wollte.

Jetzt die natürlich die Frage, gäbe es für login() auch eine legitime Verwendung, weil sonst könnte der Javascriptsyntaxchecker ja einfach mal vorher meckern.

Die Antwort ist leicht: Ja, die gibt es.

function test() {

     if ( window.location.href  == "meinefiktiveURL" ) {
           return function() {
                alert("Hallo");
           };
     }

     return function() { alert("Hier sind Sie falsch"); };
};

$("alarmknopf").onclick = test();

Damit sich darin ein Sinn ergibt, habe ich eine IF-ELSE Anweisung benutzt. Ich kann also dynamisch festlegen was passieren soll, wenn der Alarmknopf gedrückt wird. Vorteil, die IF-Abfrage wird nur einmal ausgeführt, nicht ständig, wenn jemand auf den Knopf drückt. Das ist natürlich bei einem einmaligen Event egal, aber bei Funktionen die mehrere tausend mal pro Sekunde aufgerufen werden, kann das grade bei Javascript zum Flaschenhals werden.

Natürlich kann man das auch so machen wie folgt, aber dann muß man das für jeden Knopf machen – Folge: es verbraucht mehr Ressourcen:

$("alarmknopf").onclick = function () {

        if ( window.location.href  == "meinefiktiveURL" ) {
                alert("Hallo");
        } else {
                alert("Hier sind Sie falsch");
        };
};

FireFox per SSH zum X11 forwarden

Serverfarmen bei Hostern und Unirechenzentren haben zwei Dinge gemeinsam: Es ist dort ziemlich ungemütlich und die Mitarbeiter müssen auf den Servern trotzdem ab und an Desktopanwendungen ausführen. Jeder der mal als studentische Hilfskraft gearbeitet hat kennt das, wenn ihn sein Mitarbeiter da hinschickt, um was zu machen.

Es gibt dazu allerdings Alternativen:

Man könnte heute sowas wie TeamViewer, VNC oder RemoteDesktop benutzen. Wenn man den ganzen Desktop sehen will, ist das eine feine und sehr nützliche Sache. Oft aber möchte man nur ein Programm ausführen und das unkompliziert und schnell. Den ganzen Desktop ständig zu übermitteln, ist nicht hilfreich. Also haben sich die UNIX Entwickler bereits in den 80zigern des letzten Jahrtausends eine Lösung einfallen lassen, die auch heute noch funktioniert:

das X11-Forwarding

X11-Forwarding leitet Anfragen an den lokalen X11-Display-Server ( der sorgt für das Bild auf einem Linuxrechner )  an eine externe IP Adresse um. Das geht, weil Linuxprogramme von vornherein in einer Client-Server-Umgebung arbeiten. D.b. daß die Programme im Gegensatz zu Windows eine Netzwerkschnittstelle aufrufen um mit dem Display zu sprechen. Damit kann das Display an einem anderen Ort stehen als wo das Programm ausgeführt wird und wenn es auf der anderen Seite der Erde oder im Weltraum ist.

Einziger Haken der Sache, je weiter die Geräte auseinander sind, desto langsamer reagiert das Programm auf Eingaben, weil die Daten erstmal auf die Reise geschickt werden müssen. Die resultierenden Wartezeiten nennt man Latenz.

WOW oder EVE-Online wollen Sie so nicht unbedingt spielen 😉 ( aber es wäre möglich )

Sie brauchen:

einen Linux/Unix Server mit installierten X11 Komponenten und einem SSH-Server. Den nennen wir mal „E“ für Entfernt.
Passend dazu einen Linux/Unix Rechner an dem man das Ergebnis sehen will, den nennen wir mal „L“ für Lokal.

Auf L sollte SSH installiert sein und ein X11-Server laufen. Wenn Sie grade davor sitzen und das hier lesen können, dürfte das bereits der Fall sein. Wenn Sie nur einen Windowsrechner haben, installieren Sie sich XMING ( Nein, nicht verwandt mit Xing ).

Achtung Windowsuser: Sie brauchen auch ein vollwertiges SSH Programm um weiter machen zu können und zwar eins, daß in der Konsole ausgeführt wird. Wenn Sie nur ein SSH Terminalprogramm haben, wärs möglich daß dies X11 Forwarding für Sie unterstützt. Machen Sie sich bitte schlau wie Sie das dort aktivieren.

Die Konfiguration

Auf E ändern wir zunächst die /etc/ssh/ssh_config und aktiveren dort Trustedforwarding:

X11TrustedForwarding yes

Das wars schon.

Von L aus verbinden wir uns mit dieser Option zu E :

ssh -C -Y username@servername

Je nach lokaler SSH Umgebung müssen Sie hier noch Ihr Passwort eingeben, ich kann Ihnen nur einen SSH-Agent empfehlen, da sparen Sie sich sehr viel Getippe.

-Y aktiviert X11TrustedForwarding
-C aktiviert die Kompression, damit geht es etwas schneller.

Auf E geben Sie jetzt mal ein :

echo $DISPLAY

da müßte kommen :

localhost:10.0

jetzt starten Sie einfach das gewünschte Programm, z.b. Firefox. Das geht auch direkt in einem Rutsch:

[marius@eve ~]$ ssh -C -Y root@c1 "firefox"

(process:31671): GLib-CRITICAL **: g_slice_set_config: assertion `sys_page_size == 0' failed
Gtk-Message: Failed to load module "pk-gtk-module"
Gtk-Message: Failed to load module "canberra-gtk-module"

An Fehlermeldungen müssen Sie sich jetzt leider gewöhnen, die sieht man normalerweise ja nicht, weil man die Programme nicht in der Konsole startet. Diese erwarten zurecht eine korrekte X11 Umgebung, die SSH aber nicht gehen kann. Das macht aber i.d.R. keine Probleme. Einfach ignorieren 😉

Das wars schon. Die X11 Verbindung wird durch SSH getunnelt und dabei praktischerweise noch verschlüsselt.

Warum könnte man sowas brauchen ?

Stellen Sie sich mal vor, Sie möchten ein Programm A von einem Server B auf Ihren Server E bekommen, daß 2-5 GB groß ist.

Wenn Sie das jetzt erstmal zu sich und dann auf den Server E kopieren, dauert das Stunden bis Tage, je nach DSL Leitung.

Wenn Sie das aber direkt auf E machen, dauert es ggf. nur Minuten, weil Sie dort 100 Mb/s oder gar Gb/s Anbindungen haben.

Normalerweise würde man sowas mit WGET machen, aber z.b. Oracle gängelt Webseitenbesucher erst noch mit  Cookies und Javascripten, nur damit man Java nicht direkt kopieren kann. Da kommt ein vollwertiger Firefox sehr gelegen.