0

I have a task in Javascript that requires continuous execution. I have a list of audio files stored as buffers (audioBuffer), I wish to play. However there are audio files being constantly appended to that list, so I use a while loop to monitor it. I constantly get the first buffer, play its audio, and dequeue it. However, when I run this function, it makes my browser hang, even though the loop is in an async wrapper. Why is this? Shouldn't async largely prevent my browser from freezing?

Code:

function playAudioQueue() {
                const player = new Audio();

                (async () => {
                  while (true) {
                    const audioBuffer = audioQueue[0];

                    if (audioBuffer) {
                      const base64Audio = base64Prefix + arrayBufferToBase64(audioBuffer);

                      player.src = base64Audio;

                      await player.play();

                      audioQueue.shift();
                    };
                  };
                })();
              };
3
  • Code makes no sense, what are you actually trying to accomplish. Commented Jul 29, 2021 at 16:33
  • @epascarello I stated in the post. I have a list of audio files stored as buffers, I wish to play. However there are audio files being constantly appended to that list, so I use a while loop to monitor it. Commented Jul 29, 2021 at 16:36
  • 1
    play is not asynchronous, so not sure what you are expecting. Better off with a different model where an event is triggering saying something was added, if you can do that, you need a better way to monitor for things being added because a an infinite while loop is just going to lock up the browser. Commented Jul 29, 2021 at 16:40

2 Answers 2

1

You are basically creating an infinite loop. It will lock up the browser. You need to basically do a queue type thing where it keeps checking without using a loop. You can use ended to know when the file is done playing

const audioQueue = [];

function playNext() {
  // grab the next thing to play
  const nextFile = audioQueue.shift();

  // if nothing there, check again in a short time
  if (!nextFile) {
    window.setTimeout(playNext, 1);
    return;
  }

  // Create a new player
  const player = new Audio();
  const base64Audio = base64Prefix + arrayBufferToBase64(nextFile);

  // when done, load up next thing to play
  player.addEventListener("ended", playNext);
  player.src = base64Audio;
  player.play();
}

playNext();
Sign up to request clarification or add additional context in comments.

4 Comments

I'll try this also, thanks for the answer!
Mind that you keep adding an event listener every song, which will cause you to skip songs after the 2nd song.
@KelvinSchoofs it is a new instance of the player each time. I am not using one instance. I could have done that, but did not.
Ah, true. Still, that would create a new Audio each call, although I guess not too big of a deal.
1

According to MDN Web Docs:

A Promise which is resolved when playback has been started, or is rejected if for any reason playback cannot be started.

One problem might be that in your browser it immediately resolves since you're using a data: URL which doesn't need to wait for any network requests.

A bigger logical problem in your code is that you seem to expect that await player.play() will wait until the song finished playing. This is not the case, which most likely is not what you expect.

4 Comments

Oh, player.play() instantly resolves. I guess I should use audio.onended instead. Thanks!
You could do something like await new Promise(r => audio.addEventListener(r, { once: true })). IIRC that's the correct way of having addEventListener automatically unregister the handler after the first time it fires.
@Crupeng Also don't forget to mark this answer as the solution to your question.
I'll try to see if it works, I am putting these suggestions in my code right now. I will mark after checking.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.