Weiße Ziege: async verträgt sich nicht mit dem eventListener

Gemäß der Wikiseite

Event-Handler_registrieren wollte ich onclick-Funktionen durch Event-Handler ersetzen. (Die Historie ist nicht so wichtig.)

Dabei hat die js-Datei minimal.js mit dem Inhalt

document.addEventListener('DOMContentLoaded', function () {
	document.querySelector('#mehrLesenepau')
		.addEventListener('click', klickverarbeitung);
	function klickverarbeitung() {
        alert("HAllo");
	}
});

Im head des HTML: <script async src="/js/minimal.js"></script>

ziemlich genau nichts gemacht: Keine Fehlermeldung, nichts. Der Debugger hielt gerade einmal beim Laden der Seite in der ersten Zeile an. Erst nachdem ich async entfernt habe, funktioniert es.

Nun habe ich eine Frage und eine Anregung:

Frage: Woran könnte das liegen? Anregung: Könnte man das in irgendeiner Form auf der o.g. Wikiseite als Hinweis ergänzen, auf dass mein Nächster sich ein paar Stunden Fehlersuche ersparen kann?

akzeptierte Antworten

  1. Hi,

    document.addEventListener('DOMContentLoaded', function () {
    	document.querySelector('#mehrLesenepau')
    		.addEventListener('click', klickverarbeitung);
    	function klickverarbeitung() {
            alert("HAllo");
    	}
    });
    

    in der 3. Zeile verwendest Du klickverarbeitung, welches erst eine Zeile später definiert wird.

    (ich gebe zu, ich weiß nicht, ob das ein Problem ist, ich find's zumindest verdächtig)

    cu,
    Andreas a/k/a MudGuard

    1. das ist kein problem. Wenn ich das async ausstelle, geht es ja.

    2. Tach!

      in der 3. Zeile verwendest Du klickverarbeitung, welches erst eine Zeile später definiert wird.

      (ich gebe zu, ich weiß nicht, ob das ein Problem ist, ich find's zumindest verdächtig)

      foo();
      
      function foo() { console.log('foo'); }
      

      Eine benannte Function kann man an beliebiger Stelle definieren und auch davor aufrufen. Die Funktion wird zur Compile-Zeit (oder wie auch immer man das bei Javascript nennt) angelegt, bevor das Script gestartet wird.

      foo();
      
      const foo = function() { console.log('foo'); }
      

      So geht es aber nicht, weil die Variable erst zur Laufzeit erstellt wird, und beim Funktionsaufruf noch nicht existiert.

      dedlfix.

      1. Hallo dedlfix,

        der Vorgang heißt "hoisting" (heben) und sollte zu den "dubious parts" von JavaScript gerechnet werden. Definitiv nicht zu den "good parts".

        Ich habe das vor vier Jahren (meine Güte, wie die Zeit rennt) hier und hier aufgeschrieben.

        Vielleicht nicht deutlich genug...

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Tach!

          der Vorgang heißt "hoisting" (heben) und sollte zu den "dubious parts" von JavaScript gerechnet werden. Definitiv nicht zu den "good parts".

          Gut. Wenn ich mir dazu die MDN-Beschreibung ansehe, ist Hoisting ein theoretisches Konstrukt. Praktisch passiert wohl das was man aus anderen Systemen her kennt. Also dass die Funktions- und Variablendeklarationen (nur var und abzüglich eventueller Initialisierungen) zur Compile-Zeit im Speicher abgelegt werden, bevor das Script läuft. Und somit sieht es so aus, als ob sie an den Anfang verschoben worden wären.

          dedlfix.

  2. Hi there,

    Frage: Woran könnte das liegen?

    Ganz einfach, in der Verbindung async und listeners läufst Du schnell in Timingprobleme.

    Anregung: Könnte man das in irgendeiner Form auf der o.g. Wikiseite als Hinweis ergänzen, auf dass mein Nächster sich ein paar Stunden Fehlersuche ersparen kann?

    Die eigentliche Frage ist aber, wozu Du/jemand die Skript-Datei überhaupt asynchron laden willst/will, das macht man ja normalerweise nicht...

      1. Hi there,

        https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/DOM/Einbindung_in_HTML#Fazit:_in_den_head

        liest sich so, als ob das kein Problem wäre.

        Das nimmt aber weder Bezug auf die konkrete Problematik noch auf meine Frage, wozu Du das Skript überhaupt mit async eingebunden/geladen hast. An sich ist das natürlich kein Problem, aber wenn es für Dich keines gewesen wäre, dann hättest Du hier die Frage ja nicht gestellt...😉

        1. Also ich hab verstanden, dass das irgendwie Quatsch war, async mit DOMContentLoaded zu kombinieren, aber ich will meine Anfängerperspektive noch mal ein bisschen ausführen: Ich habe mir beim Schreiben meines Javascripts nicht so viele Gedanken gemacht, was wann geladen wird und was voraussetzt (und vielleicht kann ich verallgemeinern: Man macht sich als Anfänger nicht so viele Gedanken ...). Und so habe ich auch die Hinweise bei https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/DOM/Einbindung_in_HTML#Fazit:_in_den_head nicht wirklich verstanden und durchdacht, sondern viel mehr imitiert. So kommt es halt, dass ich in etwa dachte:

          1. async ist "gut". Da werden irgendwelche Aufgaben parallel oder in einer sinnvollen Reihenfolge verarbeitet.
          2. Später wollte ich dann die onclick-commands durch eventListener ersetzen. (Grob gesagt, weil das "gut" (oder "zeitgemäß") ist. So denke ich, weil ich mit der Gesamtheit der Informationen, was das für einen Unterschied macht, überfordert bin.) Und natürlich hatte ich dann keine Ahnung, wieso das Script so gar nichts tut, wieso das, was da in eurem Wiki steht, wie man das mit dem EventListener macht, auf meinem Computer nicht funktionieren will, weil ich auch längst vergessen hatte, dass ich da irgendwann mal async ins HTML geschrieben hatte.

          Ich würde nun eigenmächtig bei der genannten Wikiseite idiotensicher hinzufügen,

          dass man bei Scripten, die DOMContentLoaded-Events enthalten, das async weglassen muss,

          hab aber hier erstmal geschrieben, weil ihr besser wisst, ob async und DOMContentLoaded-Events in manchen Fällen doch sinnvoll zusammenpassen. Jetzt, beim dritten Lesen wird mir bewusst, dass der "Beachten Sie"-Hinweis dort eigentlich genau das aussagt. Vorher habe ich mir nicht so viele Gedanken gemacht, was Laden und was Parsen bedeutet usw.

          Ich hoffe, ich habe mich einigermaßen verständlich gemacht.

          Das Tutorial "Einstieg" ist so liebevoll kleinschrittig.

          Freundliche Grüße,
          Weiße Ziege

          1. Hi there,

            [...] wieso das, was da in eurem Wiki steht, wie man das mit dem EventListener macht, auf meinem Computer nicht funktionieren will, weil ich auch längst vergessen hatte, dass ich da irgendwann mal async ins HTML geschrieben hatte.

            Das ist nicht mein Wiki, nur der Vollständigkeit halber. Ich habe das von Dir monierte Kapitel auch niemals gesehen oder gelesen, mein Einwand war ein prinzieller:

            Ich würde nun eigenmächtig bei der genannten Wikiseite idiotensicher hinzufügen,

            dass man bei Scripten, die DOMContentLoaded-Events enthalten, das async weglassen muss,

            nämlich jener, daß man schon ein äusserst speziellen Grund haben muß, ein Skript asynchron einzubinden, oder, andersrum, vermutlich deshalb vorher keiner auf die Idee gekommen ist, das extra anzuführen, weil's eben eher bis ziemlich absurd ist; etwas so in der Art: bei einer Anweisung für das richtige Radfahren schreibt ja auch keiner dazu, daß man Taucherbrille und Flossen weglassen muß

            Ich hoffe, ich habe mich einigermaßen verständlich gemacht.

            Ja, absolut, und es ist ja auch nix passiert. Im Grunde genommen ein Klassiker - programmieren lernt man fast nur durch Probieren und aus den Fehlern, die man dabei macht (oder, wie Bob Ross es auszudrücken pflegte, Fehler gibt es nicht, nur lauter lustige Zwischenfälle😉)...

            1. Hallo,

              bei einer Anweisung für das richtige Radfahren schreibt ja auch keiner dazu, daß man Taucherbrille und Flossen weglassen muß

              ich stelle mir das gerade ziemlich witzig vor. 🤣

              programmieren lernt man fast nur durch Probieren und aus den Fehlern, die man dabei macht

              Wenn es gut läuft, kann man auch aus Fehlern lernen, die jemand anders schon gemacht hat.

              Fehler gibt es nicht, nur lauter lustige Zwischenfälle😉)...

              There ain't no bugs, just unexpected features.

              Live long and pros healthy,
               Martin

              --
              Wer respektiert werden will, sollte zunächst damit anfangen, andere zu respektieren.
              1. Hi there,

                bei einer Anweisung für das richtige Radfahren schreibt ja auch keiner dazu, daß man Taucherbrille und Flossen weglassen muß

                ich stelle mir das gerade ziemlich witzig vor. 🤣

                ja, gell? Mit Brille geht ja noch, aber mit Flossen?😉

                Fehler gibt es nicht, nur lauter lustige Zwischenfälle😉)...

                There ain't no bugs, just unexpected features.

                naja, soweit ich das im Kopf habe, heisst's im Orignal "happy little accidents"...;)

                1. Hi,

                  Fehler gibt es nicht, nur lauter lustige Zwischenfälle😉)...

                  There ain't no bugs, just unexpected features.

                  naja, soweit ich das im Kopf habe, heisst's im Orignal "happy little accidents"...;)

                  es gibt ein Original??
                  Ich kenne nur die deutsche Abart: "Es gibt keine Bugs, nur unerwartete Features."

                  Das war jetzt nur meine persönliche Internationalisierung.

                  Live long and pros healthy,
                   Martin

                  --
                  Wer respektiert werden will, sollte zunächst damit anfangen, andere zu respektieren.
                2. Hi,

                  bei einer Anweisung für das richtige Radfahren schreibt ja auch keiner dazu, daß man Taucherbrille und Flossen weglassen muß

                  ich stelle mir das gerade ziemlich witzig vor. 🤣

                  ja, gell? Mit Brille geht ja noch, aber mit Flossen?😉

                  solange die Flossen das Gegenstück zum Klickpedal haben … 😉

                  cu,
                  Andreas a/k/a MudGuard

                  1. Hallo Andreas ,

                    solange die Flossen das Gegenstück zum Klickpedal haben … 😉

                    das wird der Durchbruch beim Triatlon: kein Zeitverlust beim Schuhe anziehen.

                    Gruß
                    Jürgen

          2. Hallo Weiße Ziege,

            ich habe in dem genannten Tutorialkapitel einmal aufgeschrieben, worauf man achten muss.

            Hoffentlich ist es verständlich.

            Rolf

            --
            sumpsi - posui - obstruxi
    1. Hallo,

      Frage: Woran könnte das liegen?

      Ganz einfach, in der Verbindung async und listeners läufst Du schnell in Timingprobleme.

      in diesem konkreten Fall vermute ich folgendes: Durch das async-Attribut sagst du dem Browser, er soll das Script irgendwann laden, "wenn er Zeit dafür hat". Und er hat Zeit dafür, wenn das Dokument fertig geladen ist. Dann ist aber das Ereignis DOMContentLoaded schon passé, ein nachträglich darauf registrierter Eventhandler wird nie mehr aufgerufen.

      Die eigentliche Frage ist aber, wozu Du/jemand die Skript-Datei überhaupt asynchron laden willst/will, das macht man ja normalerweise nicht...

      Die Frage habe ich mir auch gestellt.

      Live long and pros healthy,
       Martin

      --
      Wer respektiert werden will, sollte zunächst damit anfangen, andere zu respektieren.
  3. Hallo,

    wenn dein Script geladen ist, hat DOMContendLoaded schon gefeuert. Vor dem Setzen des Eventhandlers musst du prüfen, ob das Dokument schon geladen ist:

    if (document.readyState === 'loading') {
    	window.addEventListener("DOMContentLoaded",tuWas);
    }
    else {
    	tuWas();
    }	
    

    Gruß
    Jürgen

    1. Hallo JürgenB,

      und genau diesen Stand der Dinge habe ich jetzt im Wiki eingepflegt.

      Im hier erwähnten Tutorial, im Artikel zur Ereignisbehandlung und im Referenzartikel zu DOMContentLoaded.

      Man müsste Zeit haben, das alles zu sortieren...

      Rolf

      --
      sumpsi - posui - obstruxi