2016-12-10 2 views
0

Diese Funktion stark funktioniert nur, wenn in Array defaultArrayMelody unterschiedliche Zahlen sind - eine nach der anderen - ich meine: [5, 3, 4, 2] - es funktioniert, [5, 3 , 3, 2] - es funktioniert nicht.Ended Hörer nicht richtig funktioniert

Ich vermute 'beendet' Listener wird zweimal durchgeführt und zwei Ereignislistener zum Element hinzufügen. Dann ist die Funktion geloopt und es funktioniert nicht wie ich will. Wie man das Streben der Zuhörer zu einem beschränkt?

Java Script:

function playDefault() { 
const defaultArrayMelody = [70, 71, 69, 70]; 
const audio = defaultArrayMelody.map(el => document.querySelector(`audio[data-key="${el}"]`)); 


for (let i = 0 ; i < defaultArrayMelody.length; ++i) { 
    audio[i].addEventListener('ended',() => { 

     const index = i + 1; 
     if (index > audio.length-1) return false; 
     audio[index].play();    
    }); 
} 

audio[0].play(); 
} 

document.querySelector(`#playDefault`).addEventListener('click', playDefault); 

HTML:

<button class="button" id="playDefault">Play Default</button> 
<audio data-key="67" src="sounds/c1.wav"></audio>... 
+0

Ich nehme an, Sie wirklich wollen Duplikate im Array –

+0

ist [5,3,2,3] arbeiten? –

+0

@ JeremyKahan ja – Garrs

Antwort

0

Sobald ein ended Hörer abfeuert Sie es entfernen müssen, so wird es nicht wieder

jedoch gefeuert werden, so wie du bist Das Hinzufügen der Ereignis-Listener (auf einmal, im Grunde genommen) bedeutet, dass Sie dem Audio, das mehrmals abgespielt wird, bereits mehrere Listener hinzugefügt haben. Wenn also der wiederholte Audio-Eintrag nicht der letzte im Array ist, werden Sie Ich bekomme einige Probleme, kein Zweifel

Die ideale Lösung ist, den Hörer nur hinzufügen, sobald der Ton startet, und entfernen Sie den Hörer einmal das Ereignis ended ausgelöst wird.

Diese Antworten enthalten die Anfrag in dem Kommentar für eine optionale „Pause“ zwischen Audio-Element-Wiedergabe - dies durch eine negative Nummer im defaultArrayMelody

function playDefault() { 
    const defaultArrayMelody = [70, 71, -1000, 69, 70]; 
    const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`)); 

    var playAudio = function(index) { 
     if (audio[index]) { 
      var listener = function() { 
       this.removeEventListener('ended', listener); 
       playAudio(index + 1); 
      }; 
      if (typeof audio[index] == 'number') { 
       setTimeout(() => playAudio(index + 1), audio[index]); 
      } else { 
       audio[index].addEventListener('ended', listener); 
       audio[index].play(); 
      } 
     } 
    }; 
    playAudio(0); 
} 
document.querySelector(`#playDefault`).addEventListener('click', playDefault); 

Ein alternativen Verfahren bezeichnet wird, würde zu verwenden Promise

function playDefault() { 
    const defaultArrayMelody = [70, 71, -1000, 69, 70]; 
    const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`)); 

    audio.reduce((prev, item) => prev.then(() => new Promise(resolve => { 
     var listener = function listener() { 
      this.removeEventListener('ended', listener); 
      resolve(); 
     }; 
     if (typeof item== 'number') { 
      setTimeout(resolve, item); // item is millseconds 
     } else { 
      item.addEventListener('ended', listener); 
      item.play(); 
     } 
    })), Promise.resolve()); 
} 
document.querySelector(`#playDefault`).addEventListener('click', playDefault); 

Hier können Sie mit nicht entfernen Der Ereignis-Listener, da der Event-Listener nur das Versprechen löst - und sobald ein Versprechen gelöst ist, kann es nicht wieder aufgelöst (oder abgelehnt) werden - wodurch sichergestellt wird, dass die Sequenz nur einmal in der Reihenfolge abgespielt wird. Jedoch in dem obigen Code enthalten ich die removeEventListener ... ohne es sieht der Code wie

function playDefault() { 
    const defaultArrayMelody = [70, 71, -1000, 69, 70]; 
    const audio = defaultArrayMelody.map(el => el < 0 ? -el : document.querySelector(`audio[data-key="${el}"]`)); 

    audio.reduce((prev, item) => prev.then(() => new Promise(resolve => { 
     if (typeof item== 'number') { 
      setTimeout(resolve, item); // item is millseconds 
     } else { 
      item.addEventListener('ended', resolve); 
      item.play(); 
     } 
    })), Promise.resolve()); 
} 
document.querySelector(`#playDefault`).addEventListener('click', playDefault); 
+0

Alle Methoden funktionieren! Weißt du, wie man zwischen einigen Elementen eine zweite Pause einfügt? Meine Lösung ist 0 zum Array hinzuzufügen.Und in html: Gibt es einen besseren Weg? Ich vermute, dass ich für die anderen zwei wahrscheinlich Split-Array brauche. – Garrs

+0

@Garrs - Ich habe die Antwort bearbeitet (es wurde ein bisschen lang), um eine mögliche Methode aufzunehmen, eine Pause zwischen Elementen einzufügen - siehe Codeänderungen - hoffe, dass dir das auf irgendeine Weise hilft –