Trollwut: Javascript
Freitag bemerkte ich mal wieder wie froh ich bisher sein konnte so wenig mit Javascript zu tun gehabt zu haben. Ausgangslage war die Einbindung zweier etwas größerer JS-Dateien in eine Seite, die ihrerseits wieder alle Möglichen Daten per Ajax einbanden. Die Ursprungsversion sah also ziemlich so aus wie man es erwarten würde.
<script src="http://url.1" />
<script src="http://url.2" />
<body onload="run()">
Das hat so eigentlich funktioniert (auch wenn ich einige Zeit für die ganzen Einstellungen in run() benötigte) und zeigte eine eingebundene JS-Applikation sofort nach dem Laden an. Zusätzlich gab es noch einen einfachen Link auf die JS-Anwendung in einem neuem Fenster mit den wichtigsten Parametern in der URL.
Leider war die Anwendung etwas Umfangreicher und verlangsamte die Seite ziemlich drastisch. Also zurück an die Tastatur und eine zweite Version erstellt. Wieder dauerte es eine Weile die Anpassungen vorzunehmen, immerhin musste ein mehrfaches aufrufen von run() verhindert werden, als einfachste Methode erwies es sich einfach als erstes in run() das Objekt mit der ID blah zu verstecken.
<script src="http://url.net/1" />
<script src="http://url.net/2" />
<p id="blah">
<a href="#" onload="run()">start me up!</a>
</p>
Auch diese Variante funktionierte problemlos, auch war sie um ca. die Hälfte schneller als die vorherige Version und rief die JS-Anwendung erst auf wenn sie von jemandem benötigt wurde. Leider wurden die Javascript-Dateien noch beim Aufruf der Seite geladen, was aufgrund ihrer Größe noch immer weit über die Hälfte der Ladezeit insgesammt ausmachte.
Also musste ich versuchen auch diese beiden Dateien bei Bedarf nachzuladen.
Mit Snookies Hilfe war dann auch relativ schnell eine etwas geschicktere Lösung gefunden. http://www.javascriptk...
Woraus sich folgender Code ergab:
<script type='text/javascript'>
function load()
{
loadjsfile('http://url.net/1');
loadjsfile('http://url.net/2');
run();
}
function loadjsfile(filename)
{
var fileref=document.createElement('script')
fileref.setAttribute('type','text/javascript')
fileref.setAttribute('src', filename)
document.getElementsByTagName('head')[0].appendChild(fileref)
}
</script>
<p id="blah">
<a href="#" onload="load()">start me up!</a>
</p>
Das Problem an dieser Lösung war aber dass die run()-Funktion nun aufgerufen wurde bevor die beiden js-Dateien fertig herunter geladen waren. Beinahe hätte ich zu der einfachsten Lösung gegriffen, "run()" durch setTimeout('run()', 1000) ersetzt und den Nutzer halt einfach 10s warten lassen. Wenn die Dateien in 10s nicht fertig geladen waren (Modem?) hätte es dieser Idiot halt mit der Alternativversion im neuen Fenster versuchen sollen oder könnte einfach nochmal klicken.
Da ich aber doch um einen (wenigstens etwas) besseren Code bemüht war schrieb ich den Code zu folgender Version um:
<script type='text/javascript'>
function teil1()
{
var fileref=document.createElement('script')
fileref.setAttribute('type','text/javascript')
fileref.setAttribute('onload','teil2();')
fileref.setAttribute('src', 'http://url.net/1')
}
function teil2()
{
var fileref=document.createElement('script')
fileref.setAttribute('type','text/javascript')
fileref.setAttribute('onload','run();')
fileref.setAttribute('src', 'http://url.net/2')
document.getElementsByTagName('head')[0].appendChild(fileref)
}
</script>
<p id="blah">
<a href="#" onload="teil1()">start me up!</a>
</p>
Das war nun aber wirklich eine Version mit der man zufrieden sein könnte, die Dateien werden auf Klick geladen und formschön im Quellcode eingebaut, sobald die erste Datei fertig ist wird die zweite in Angriff genommen und nach deren Vollendung auch die JS-Anwendung aufgerufen und der Link zum Aufruf versteckt.
Sicher der Code war etwas länger geworden (Erinnert sich noch wer an die 3 Zeilen vom Anfang?), aber was solls? Hauptsache der Code funktioniert und das tat er ja auch... im Firefox.
Internet Exploder jedoch machte keinerlei Anstallten die Zweite Datei einzubinden oder gar run() auszuführen. Nach etwas längerer Recherche war dann auch klar warum. IE unterstützt kein onload in Script-Tags.
Also musste ich meinen Quellcode erneut umstellen und wieder entschied ich mich gegen die einfachste Version (ich teste solange in einer Schleife ob die Dateien geladen sind bis ich true bekomme) zu gunsten der CPU-Auslastung.
<script type='text/javascript'>
function load()
{
loadjsfile('http://url.net/1');
loadjsfile('http://url.net/2');
versuchs();
}
function loadjsfile(filename)
{
var fileref=document.createElement('script')
fileref.setAttribute('type','text/javascript')
fileref.setAttribute('src', filename)
fileref.setAttribute('onload', 'versuchs()')
document.getElementsByTagName('head')[0].appendChild(fileref)
}
function versuchs()
{
if(typeof(OpenLayers)!= 'undefined' && typeof(OpenLayers.Layer.OSM)!= 'undefined')
{
init();
}
else
{
setTimeout('versuchs();',100)
}
}
</script>
<p id="blah">
<a href="#" onload="load()">start me up!</a>
</p>
Ja dieser Code funktioniert. Er tut nichts anderes als eine bereits programmierte Anwendung (deren Startcode bereits in 2 Dateien geliefert wird) aufzurufen. Dabei ist weder die Bereitstellung der Parameter, die Configuration der Anwendung und ihres Aussehens noch irgendwelches andere Zeug enthalten. Nichteinmal das Verstecken des Startlinks ist hier mit notiert.
Dennoch sind aus den anfänglichen 3 Zeilen mal eben reichlich 30 Zeilen, mit 3 Funktionen und allen möglichen Umgehungen von browserspezifischen Problemen, geworden. Ich habe mehrere Stunden mit der Findung eines Lösung dieses Problemes zugebracht und bin beinahe an den verschiedenen Browserverhaltensweisen verzweifelt.
Was ich damit sagen will: es wird schwer eine einfachere Aufgabe zu finden die man mit Javascript lösen muss und dennoch fließt eine Unmenge Energie und Aufwand in solchen derartig schlechten Code der nichtmal irgendwelche Erfahrungswerte auf irgendeinem Gebiet außer "mit Javascript und Browsern umgehen" bringt.
Das Ziel einer Programmiersprache ist meiner Meinung nach schon immer einem menschlichen Programmierer zu ermöglichen dem Computer auf dem einfachsten Wege mitzuteilen was er tun soll. Die Aufgabe von Javascript ist aber vielmehr dem Programmierer Wege finden zu lassen wie er die vielen verschiedenen Hindernisse umgeht, die ihm die Browserentwickler in den Weg werfen.
Auch wenn manche total begeistert von Javascript sind, für mich ist und bleibt diese Sprache völlig unbrauchbar. Sie ist umständlich, langsam, muss für jede zusätzliche Zielplatform komplett angepasst werden und erzeugt nichts so sehr wie Agressionen.
Natürlich ist die Situation auf diesem Gebiet bereits besser geworden, die Browserhersteller nähern sich einander an, die Ausführung wird über Precompiler beschleunigt (zumindest wird das wohl jetzt großflächig kommen) und Bibliotheken ebnen die restlichen Abstände und Unterschiede zwischen den Platformen ein.
Dennoch ist die Sprache imho "broken by design", sie zeigte schöne Ansätze aber das Ziel wurde verfehlt. Bastelt nicht weiter daran herum sondern definiert euch lieber eine komplett neue Sprache bei der ihr die guten Ansätze verwendet und die Lücken (wie zu ungenaue Definition des "Standards") vermeidet!