event abfangen und in Warteschleife parken
Tincan
- javascript
Hi Community,
ich habe derzeit folgendes problem:
...
<a href="target.html" onMouseup="javascript()">ziel</a>
...
da ich die einzelnen javascripts aus performancegründen nachgelagert lade und nachträglich in das DOM einfüge kann ich nicht sicher sein, ob die function javascript() schon geladen ist wenn ein user auf den link klickt.
ich bräuchte jetzt Hilfe dabei, alle (nicht näher definiert) javascript functionsaufrufe abzufangen und nur auszuführen wenn die function existiert. wenn nicht soll der functionsaufruf in einer Warteschleife geparkt werden. diese Warteschleife soll dann über window.setTimeout abgeprüft werden bis alle scripts geladen sind.
hoffe ich habe es einigermaßen darstellen können.
Mit freundlichen Grüßen
Hi,
da ich die einzelnen javascripts aus performancegründen nachgelagert lade und nachträglich in das DOM einfüge kann ich nicht sicher sein, ob die function javascript() schon geladen ist wenn ein user auf den link klickt.
ich bräuchte jetzt Hilfe dabei, alle (nicht näher definiert) javascript functionsaufrufe abzufangen und nur auszuführen wenn die function existiert.
Nein, das is Nonsense.
Binde stattdessen die Event *per* JavaScript an deine Elemente.
MfG ChrisB
Hallo,
da ich die einzelnen javascripts aus performancegründen nachgelagert lade und nachträglich in das DOM einfüge kann ich nicht sicher sein, ob die function javascript() schon geladen ist wenn ein user auf den link klickt.
Wenn eine so große Verzögerung zwischen der Anzeige der Seite und dem Laden des Scripts gibt, solltest du zu aller erst versuchen, diese zu minimieren. Zur Not sogar die Scripte blockierend laden.
Üblicherweise registriert man Event-Handler per JavaScript beim DOM-Ready. In dem Fall kann es nicht dazu kommen, dass nicht geladene Handler aufgerufen werden. Es kann natürlich immer noch passieren, dass User schon im Interface klicken, bevor die JavaScript-Logik geladen ist.
ich bräuchte jetzt Hilfe dabei, alle (nicht näher definiert) javascript functionsaufrufe abzufangen und nur auszuführen wenn die function existiert. wenn nicht soll der functionsaufruf in einer Warteschleife geparkt werden.
Das geht nicht ohne den Code zu ändern. Das Aufrufen einer nicht existenten Funktion sorgt für eine Exception. Die kann man zwar abfangen (window.onerror), aber nur sehr unspezifisch.
Eine Funktion zu definieren, die Aufrufe speichert, ist natürlich möglich.
var queue = [];
var callWhenReady = function(name) {
// Lese 1. bis n. Parameter in einen Array
var args = Array.prototype.slice.call(arguments, 1);
// Speichere Namen und Parameter in der Queue
queue.push({ name: name, args: args });
};
Aufruf:
callWhenReady('funktionsname', parameter…);
Dann wie du sagst periodisch prüfen, ob die globalen Funktionen existieren:
var polling = function() {
// Durchlaufe Queue und erzeuge eine neue
queue = queue.[link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce@title=reduce](function(queue, descriptor) {
// Suche globale Funktion mit dem Namen
var f = window[descriptor.name];
if (typeof f == 'function') {
// Rufe Funktion auf, füge nicht zur neuen Queue hinzu
f.apply(window, descriptor.args);
} else {
// Füge zur neuen Queue hinzu
queue.push(descriptor);
}
return queue;
}, []);
if (queue.length) {
setTimeout(polling, 100);
}
};
polling();
(ungetesteter Beispielcode)
Mathias
danke erstmal für den schon guten Ansatz der queue
ich umschreibe nochmal etwas genauer um was es mir geht.
ich habe ein php framework erstellt, dass mit einer ajax library (self made) Inhalte nachladen soll.
ich habe jedoch keinen Einfluss darauf, ob und wenn ja welche javascripte aufgerufen werden (denke es wird sich meist um eventhandler handeln). ich möchte daher alle eventhandler (oder besser alle javascript aufrufe) abfangen und prüfen ob die function dazu bereits geladen ist.
ziel ist es die javascripte klein und für spezifische zwecke zu erstellen. nutzt nun ein user z.B. einen hyperlink in dem ein eventhandler definiert ist so soll (function existiert noch nicht) das script geladen (scriptname = objectname) werden und die aufgerufene function anschliessend ausgeführt werden (so etwas wie onDemand load für JS).
...
<a href="target.html" onMouseUp="library.javascript()">Ziel</a>
...
das JS lädt daraufhin die library.js und alle library.functionname() stehen ab da zur Verfügung.
genauso müssten deshalb auch normale scriptaufrufe abgefangen werden
...
<div>
<script>
library.javascript();
</script>
</div>
...
am liebsten wäre mir eine "globale" definition bei der ich den functionsnamen (libary.javascript()) sowie die parameter des functionsaufrufes bekomme, die in einer interception weiterverarbeitet werden kann.
Hallo,
am liebsten wäre mir eine "globale" definition bei der ich den functionsnamen (libary.javascript()) sowie die parameter des functionsaufrufes bekomme, die in einer interception weiterverarbeitet werden kann.
So etwas gibt es in JavaScript nicht. Außer dem sehr unspezifischen window.onerror, wie gesagt.
Davon abgesehen kann man sich eine solche Nachlade-Logik programmieren, aber es ist schwierig, das mit Event-Handler-Attributen umzusetzen. Daher der Hinweis von ChrisB und mir auf das Registrieren von Event-Handlern mit JavaScript.
JavaScript ist funktional, sodass sehr einfach ist, Funktionen in andere zu verpacken. Die äußere Funktion lädt dann das fragliche Modul und führt bei Erfolg die innere Funktion aus. Beispiel:
<button id="button">Klick mich</button>
// Erzeugt eine Funktion mit einer Abhängigkeit
var dependency = function(module, f) {
return function() {
// Merke Kontext und Parameter des Aufrufs
var originalThis = this, originalArguments = arguments;
// Lade das Modul
jQuery.getScript('/scripts/' + module + '.js', function() {
// Rufe die Funktion mit dem Originalkontext und den Originalparametern auf
f.apply(this, arguments);
});
};
};
// Verpacke den Event-Handler in eine Lade-Funktion
// Abhängigkeit: Modul »helloWorld«
var eventHandler = dependency('helloWorld', function() {
// Wenn diese Funktion ausgeführt wird, existiert helloWorld
helloWorld.hello();
});
// Registriere einen Event-Handler
document.getElementById('button').[link:http://molily.de/js/event-handling-fortgeschritten.html@title=addEventListener]('click', eventHandler);
So funktioniert letztlich auch das Lazy-Loading in großen JavaScript-Anwendungen. JavaScript-Anwendungen verwenden eher Module-Loader wie Require.js, die auf AMD oder Common.js basieren.
Mathias