Destructor: setInterval läuft Amok

Hallo - Es ist wieder mal zum Kinder werfen. setInterval läuft mir davon und ich weiß einfach nicht, was da genau falsch läuft... (ARGH)

Die Grundidee klingt dabei so einfach wie sie sich in der Umsetzung als tückisch herausstellt: Ich habe [exemplarisch] eine Reihe von <DIV>s:

<div id="bsp_1" class="bsp"><p>Bsp_1</p></div>
<div id="bsp_2" class="bsp"><p>Bsp_2</p></div>
<div id="bsp_3" class="bsp"><p>Bsp_3</p></div>
<div id="bsp_4" class="bsp"><p>Bsp_4</p></div>

...wobei sich sämtliche <DIV>s via CSS verstecken [.bsp { display: none;}].

Via setInterval soll nun "bsp_1" 3 Sekunden, "bsp_2" und "bsp_3" 5 Sekunden angezeigt werden, bevor das Programm permanent auf "bsp_4" landet.

UND DAS GEHT [offenbar NICHT] SO:

<script type="text/javascript">


function Hauptprogramm() {
  
  /* Variablen für die Durchläufe werden definiert */
  
  var Durchlauf_3s;
  var Durchlauf_5s_1;
  var Durchlauf_5s_2;
  
  
  /* Variable "aktiv" [definiert, welches DIV anzuzeigen und welches zu verstecken ist] */
  
  var aktiv = 1;
  
  /* Das erste DIV wird aktiviert bzw. angezeigt */
  document.getElementById("bsp_" + aktiv).style.display = "block";
  
  /* aktiv wird auf 2 gesetzt */
  aktiv += 1;
  
  
  /* setInterval: Wenn "aktiv" größer 1 ist [ist der Fall], so wird "aktiv" minus 1
  [daher das gerade aktivierte bzw. angezeigt DIV] versteckt und "aktiv" [jetzt 2] angezeigt.
  Dies soll nach einem Interval von 3 Sekunden geschehen [siehe unten].
  */
  
  Durchlauf_3s = setInterval(function () {
    if (aktiv > 1) {
       document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
    }
    document.getElementById("bsp_" + aktiv).style.display = "block";
    
	/* aktiv wird auf 3 gesetzt */
	aktiv += 1;
		
	/* Das Interval wird nach einem Durchlauf beendet. */
    clearInterval(Durchlauf_3s);
    
  }, 3000) // nach einem Interval von 3 Sekunden


/* 2. Durchlauf: funktioniert analog zum 1. Durchlauf.
*/

Durchlauf_5s_1 = setInterval(function () {
    if (aktiv > 1) {
       document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
    }
    document.getElementById("bsp_" + aktiv).style.display = "block";
    aktiv += 1;
    clearInterval(Durchlauf_5s_1);
  }, 5000) 


  /* 3. Durchlauf */

Durchlauf_5s_2 = setInterval(function () {
    if (aktiv > 1) {
       document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
    }
    document.getElementById("bsp_" + aktiv).style.display = "block";
    aktiv += 1;
    clearInterval(Durchlauf_5s_2);
  }, 5000)
  
}
window.addEventListener("load", Hauptprogramm);

</script>

Das Resultat: Bsp_1 wird noch drei Sekunden angezeigt, danach springt das Programm auf Bsp_2, um in weiterer Folge sofort auf Bsp_4 zu landen...

...was läuft hier verkehrt?!

Danke für eure Analysen! Destructor.

  1. Ach du liebe Zeit.

    Ich wollte Vorschau, nicht speichern (bitte um Entschuldigung!).

    Hier nochmals der Code, korrekt formatiert:

    Html:

    <div id="bsp_1" class="bsp"><p>Bsp_1</p></div>
    <div id="bsp_2" class="bsp"><p>Bsp_2</p></div>
    <div id="bsp_3" class="bsp"><p>Bsp_3</p></div>
    <div id="bsp_4" class="bsp"><p>Bsp_4</p></div>
    

    Javascript:

    function Hauptprogramm() {
      
      /* Variablen für die Durchläufe werden definiert */
      
      var Durchlauf_3s;
      var Durchlauf_5s_1;
      var Durchlauf_5s_2;
      
      
      /* Variable "aktiv" [definiert, welches DIV anzuzeigen und welches zu verstecken ist] */
      
      var aktiv = 1;
      
      /* Das erste DIV wird aktiviert bzw. angezeigt */
      document.getElementById("bsp_" + aktiv).style.display = "block";
      
      /* aktiv wird auf 2 gesetzt */
      aktiv += 1;
      
      
      /* setInterval: Wenn "aktiv" größer 1 ist [ist der Fall], so wird "aktiv" minus 1
      [daher das gerade aktivierte bzw. angezeigt DIV] versteckt und "aktiv" [jetzt 2] angezeigt.
      Dies soll nach einem Interval von 3 Sekunden geschehen [siehe unten].
      */
      
      Durchlauf_3s = setInterval(function () {
        if (aktiv > 1) {
           document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
        }
        document.getElementById("bsp_" + aktiv).style.display = "block";
        
    	/* aktiv wird auf 3 gesetzt */
    	aktiv += 1;
    		
    	/* Das Interval wird nach einem Durchlauf beendet. */
        clearInterval(Durchlauf_3s);
        
      }, 3000) // nach einem Interval von 3 Sekunden
    
    
    /* 2. Durchlauf: funktioniert analog zum 1. Durchlauf.
    */
    
    Durchlauf_5s_1 = setInterval(function () {
        if (aktiv > 1) {
           document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
        }
        document.getElementById("bsp_" + aktiv).style.display = "block";
        aktiv += 1;
        clearInterval(Durchlauf_5s_1);
      }, 5000) 
    
    
      /* 3. Durchlauf */
    
    Durchlauf_5s_2 = setInterval(function () {
        if (aktiv > 1) {
           document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
        }
        document.getElementById("bsp_" + aktiv).style.display = "block";
        aktiv += 1;
        clearInterval(Durchlauf_5s_2);
      }, 5000)
      
    }
    window.addEventListener("load", Hauptprogramm);
    
  2. @@Destructor

    UND DAS GEHT [offenbar NICHT] SO:
    <script type="text/javascript">

    Stimmt.

    Das geht mit CSS-Animations, s.a. CSS-Tricks.

    Sonst stirbt ein Kätzchen.

    LLAP

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. @@Destructor

      UND DAS GEHT [offenbar NICHT] SO:
      <script type="text/javascript">

      Stimmt.

      Das geht mit CSS-Animations, s.a. CSS-Tricks.

      Sonst stirbt ein Kätzchen.

      LLAP

      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)

      DONNERWETTER! Na der Abgang des kleinen Pelze-Buben MUSS um jeden Preis vermieden werden!

      Trotzdem MUSS ich einfach wissen, was ich da falsch gemacht habe... ...ist ja sonst wie ein Krimi, der den Mörder nicht preisgibt!

      [Tut mir leid, aber wenn etwas nicht funzt, MUSS ich dem einfach auf den Grund gehen, bin da zugegeben ein wenig pedantisch...]

  3. Hi,

    Via setInterval

    Warum?

    soll nun "bsp_1" 3 Sekunden, "bsp_2" und "bsp_3" 5 Sekunden angezeigt werden, bevor das Programm permanent auf "bsp_4" landet.

    Durchlauf_3s = setInterval(function () { clearInterval(Durchlauf_3s); }, 3000) // nach einem Interval von 3 Sekunden

    Die Tatsache, daß Du beim ersten Ablauf des Intervalls das Intervall löschst, sagt, daß Du eher setTimeout benutzen willst. Das erzeugt von vornherein nur genau einen Aufruf der übergebenen Funktion.

    Du sagst: 3 Sekunden nach Laden der Seite soll Aktion 1 passieren

    Durchlauf_5s_1 = setInterval(function () { clearInterval(Durchlauf_5s_1); }, 5000)

    Auch dieses Intervall löschst Du sofort wieder ==> setTimeout.

    Du sagst: 5 Sekunden nach Laden der Seite soll Aktion 2 passieren

    Durchlauf_5s_2 = setInterval(function () { clearInterval(Durchlauf_5s_2); }, 5000)

    Auch dieses Intervall löschst Du sofort wieder ==> setTimeout.

    Du sagst: 5 Sekunden nach Laden der Seite soll Aktion 3 passieren

    ...was läuft hier verkehrt?!

    Zusammengefaßt:
    Du sagst: 3 Sekunden nach Laden der Seite soll Aktion 1 passieren
    Du sagst: 5 Sekunden nach Laden der Seite soll Aktion 2 passieren
    Du sagst: 5 Sekunden nach Laden der Seite soll Aktion 3 passieren

    Du könntest z.B. setTimeout mit 3 Sekunden für Aktion 1, mit 8 Sekunden für Aktion 2 und mit 13 Sekunen für Aktion 3 nutzen.
    Oder das setTimeout mit 5 Sekunden in der Aktion 1 mit Aufruf von Aktion 2 auslösen, und ein weiteres setTimeout mit 5 Sekunden in Aktion 2 mit Aufruf von Aktion 3 auslösen.

    cu,
    Andreas a/k/a MudGuard

    1. Hallo Andreas,

      danke für deine Antwort!

      Habe mich in die Thematik setInterval / setTimeout eingelesen. Du hast Recht, für meine Bedürfnisse kommt wohl eher die von dir richtigerweise vorgeschlagene setTimeout - Variante in Frage.

      Liebe Grüße, Der Destructor.

    2. ...ok und schon wieder laufe ich gegen die Wand :(

      folgender Code sollte doch eigentlich dazu führen, dass zuerst "bsp_1", nach einer Sekunde "bsp_2", zwei Sekunde danach "bsp_3" und fünf Sekunden danach "bsp_4" angezeigt wird.

      • De facto wird nach einer Sekunde "bsp_4" angezeigt, des weiteren ignoriert "bsp_1" die display = "none" Anweisung.

      Javascript:

      function Hauptprogramm() {
      
      	var aktiv = 1;
      
      	var Durchlauf_1s;
      	var Durchlauf_2s;
      	var Durchlauf_5s;
      
      	document.getElementById("bsp_" + aktiv).style.display = "block";
      	aktiv++;
      
      	Durchlauf_1s = setTimeout(function() {
      	if (aktiv > 1) {
      		document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
      		document.getElementById("bsp_" + aktiv).style.display = "block";
      		}
      	}, 1000);
      	
      	aktiv++;
      	
      	Durchlauf_2s = setTimeout(function() {
      	if (aktiv > 1) {
      		document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
      		document.getElementById("bsp_" + aktiv).style.display = "block";
      		}
      	}, 3000);
      	
      	aktiv++;
      	
      	Durchlauf_5s = setTimeout(function() {
      	if (aktiv > 1) {
      		document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
      		document.getElementById("bsp_" + aktiv).style.display = "block";
      		}
      	}, 8000);
      
      } 
      
      window.addEventListener("load", Hauptprogramm);
      

      Bin für jede Hilfe zum Thema dankbar!

      LG, Destructor.

      1. Hallo Destructor,

        Bin für jede Hilfe zum Thema dankbar!

        <script>
        function init(e) {
            var aktiv = 1;
            var a = [0, 1000, 3000, 5000];
            a.forEach(function(entry) {
                setTimeout(function() {
                    Durchlauf(aktiv++)
                }, entry);
            });
        }
        function Durchlauf(aktiv) {
            if (aktiv > 1) {
                document.getElementById('bsp_' + (aktiv - 1)).style.display = 'none';
                document.getElementById('bsp_' + aktiv).style.display = 'block';
            }
            console.log('aktiv: ' + aktiv);
        }
        window.addEventListener('load', init);
        </script>
        

        einfacher ist es wenn du dein Problem in zwei Funktions-Aufrufe zerlegst und mittels der Console dein Result darauf prüfst… ob es deine Anforderungen erfüllt.

        gr qx

      2. Hi,

        ...ok und schon wieder laufe ich gegen die Wand :(

        Im Prinzip der gleiche Fehler:

        var aktiv = 1; aktiv++;

        jetzt hat aktiv den Wert 2.

        Durchlauf_1s = setTimeout(function() {

        in 1s mach was, was die Variable aktiv benutzt.

        aktiv++;

        aktiv hat jetzt den Wert 3.

        Durchlauf_2s = setTimeout(function() {

        mach in 3s was, was die Variable aktiv benutzt.

        aktiv++;

        aktiv hat jetzt den Wert 4.

        Durchlauf_5s = setTimeout(function() {

        mach in 8s was, was die Variable aktiv benutzt.

        jetzt vergeht 1s, dann läuft der 1. Timeout ab, die Funktion

        function() {
                if (aktiv > 1) {
                        document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
                        document.getElementById("bsp_" + aktiv).style.display = "block";
                        }
                }
        

        wird ausgeführt. Erinnere Dich, aktiv hat bereits den Wert 4.

        Weitere 2s später läuft der 2. Timeout ab, es wird

        function() {
                if (aktiv > 1) {
                        document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
                        document.getElementById("bsp_" + aktiv).style.display = "block";
                        }
                }
        

        aufgerufen. aktiv hat nach wie vor den Wert 4.

        Weitere 5s später läuft der letzte Timeout ab, es wird

        function() {
                if (aktiv > 1) {
                        document.getElementById("bsp_" + (aktiv - 1)).style.display = "none";
                        document.getElementById("bsp_" + aktiv).style.display = "block";
                        }
                } 
        

        aufgerufen. Die Variable aktiv hat immer noch den Wert 4.

        Durch setTimeout wird nicht das Script angehalten. Es wird sich gemerkt: rufe nach Ablauf der übergebenen Zeit die übergebene Funktion auf. In der Zwischenzeit mach mit dem Script weiter.

        Eine mögliche Lösung wäre, das Hochzählen der Variable aktiv in den Funktionen, die an setTimeout übergeben werden, zu machen.

        cu,
        Andreas a/k/a MudGuard