简体   繁体   中英

Javascript audio layering eventListener HTML5 fails on multiple iterations

I am working on putting together an audio function for use on a simple script to play notes like those on a piano. My solution to the audio tags inability to handle a new request until it has played through was to create a new audio element for every subsequent click, then set a listener to remove that element once it had played its sound. It works great except that it seems as though my event listener is overwritten, so only the last iteration of the sound is followed, leaving numerous audio elements intact and inactive.

Code:

var x = 0;
function playSound(){
  x = x + 1;
  var na = document.createElement('audio');
  na.setAttribute('id','cycle'+x);
  document.body.appendChild(na);
  var ta = document.getElementById('cycle'+x);
  var ns = document.createElement('source');
  ns.setAttribute('src','notify.wav');
  ta.appendChild(ns);
  document.getElementById('cycle'+x).addEventListener('ended', function(){
  document.body.removeChild(document.getElementById('cycle'+x));
    try{document.getElementById('cycle'+x).remove();}
    catch(err){}});
  ta.play();
}

and to preload the sound into the page:

<audio id="preloader" preload="auto"><source src="notify.wav"></source></audio>

I am wanting to have individual event listeners for each generated audio element, so that when the file has played, the element is removed.

Your problem stems from a referencing issue - by the means used in your sample code you cannot fetch the desired element in the current scope within the listener.

Safari's console tells me this:

[Error] NotFoundError: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.
(anonymous function) (_display, line 33)

Obviously all event listeners are firing correctly.

Of course you could go on a massive hunt to find the true reason behind this, but since you are looking for a solution to your problem, this should do:

Remove these lines:

document.body.removeChild(document.getElementById('cycle'+x));
try{document.getElementById('cycle'+x).remove();}
catch(err){}});

And replace them with:

this.remove();

The event listener callback will always provide the related element as this . And that is your safest route to a valid reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM