2

My goal is to iterate through an array, take the value of each element of the array as a key and play a sound clip associated with that value. The final result desired is to sequentially play the sound clips, in the order of their keys in the array.

Here is what I have tried so far:

//there are addresses associated with the color sound values 

function playSound(soundValue){
  $sound.src = soundValue;
  $sound.load();
  $sound.play();
}

function playGame(){
  simonSays = [0,1,2,3];

  var soundOptions = {
    0: yellowSound,
    1: redSound,
    2: blueSound,
    3: greenSound 
  };

  for (var i = 0; i < simonSays.length; i++){
    var callSound = soundOptions[simonSays[i]];
    setTimeout(playSound(callSound),1000 );
  }
};

This code iterates through the sequence and does wait for the setTimeout durations to finish. I receive this error:

 Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.
    playSound @ logic.js:72
    playGame @ logic.js:120
    onclick @ index.html:37

My understanding is that the audio files are interferring with each other and producing the error, but additionally there is no delay in the iteration through the sequence that allows each file to complete. I looked at these examples of other efforts to delay media execution but neither a call to $sound.ended or $sound.onended were able to prevent the iteration ahead of the audio file completion. The project will increase the length and order of the array so I need some way to control the execution of each member of the array.

Can anyone offer any advice? Thank you.

Community
  • 1
  • 1
Cameron
  • 105
  • 1
  • 11

1 Answers1

1

The setTimeout doesn't delay the loop. The loop causes every audio file to be delayed only one second. The solution would be to put the loop into a function, something like this:

simonSays = [0,1,2,3];

var soundOptions = {
  0: yellowSound,
  1: redSound,
  2: blueSound,
  3: greenSound 
};

function playGame(){
  startPlaying(0,simonSays.length);
};

function startPlaying(i,l) {
  if (i==l) return;
  var callSound = soundOptions[simonSays[i]];
  playSound(callSound);
  setTimeout("startPlaying("+(i+1)+","+l+")",1000);      
}
Richard Yan
  • 1,206
  • 8
  • 19
  • I really like the recursive call but I am still getting an error; when I set the ```setTimeout``` with the call as a string it produces this error: ```Uncaught ReferenceError: i is not defined at :1:14``` When I reference the ```startPlaying(i+1, l)``` not as a string it produces the same effect of cycling through the full range with no calls to the audio file, same as the original problem. Any thoughts? Thank you for your time. – Cameron May 12 '17 at 00:55
  • I didn't notice that problem. I've edited my post, let me know if it works! It's hard for me to debug this kind of problem because it's hard to reproduce the html you're having. – Richard Yan May 12 '17 at 00:59
  • Perfect! It was my problem accurately writing the function call, ensuring that the combination of string and number was sent worked perfectly. This was a great solution. Thank you for your time. – Cameron May 12 '17 at 01:15