Tincan: event abfangen und in Warteschleife parken

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

  1. 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

    --
    Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
  2. 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

    1. 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.

      1. 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