The event listener for 'ended' is triggering multiple times

I am in the process of developing a music app, and my goal is to have the next song automatically play when the current one ends. However, I am facing an issue where the EventListener seems to be triggered multiple times in succession - first once, then twice, and so on, with the number increasing each time it's triggered. I have searched other websites for solutions but haven't been able to find one. I hope someone here can assist me with this problem.

Just to provide some context, I'm using Vue.js for this project.

Here is a snippet of my data:

data () {
return {
  current: {},
  index: 0,
  isPlaying: false,
  api_key: '4f40bf40b2msh6d957020229b6c6p1fe925jsn4ef16ee46284',
  url_base: 'https://deezerdevs-deezer.p.rapidapi.com',
  songs: [],
  query:'',
  player: new Audio()
}
},

And here is the method I am using to play the music:

play (song) {
  if (typeof song.title != "undefined") {
    this.current = song;
    this.player.src = this.current.preview;
  }

  this.player.play();
  
  this.player.addEventListener('ended', function () {
    console.log(this.index);

    if (this.index > this.songs.length - 1) {
      this.index = 0;
    }
    this.current = this.songs[this.index];
    this.play(this.current);
  }.bind(this));

  this.isPlaying = true;
},

If anyone has any suggestions on how I can improve this functionality, I would greatly appreciate it.

Answer №1

An issue arises when each time the play method is triggered, a new event listener is attached. Consequently, when a song concludes, all previously added listeners are also activated.

There seems to be a misunderstanding that once a listener is executed, it is automatically removed. However, these listeners remain active until explicitly deleted.

To resolve this, consider placing the addEventListener call outside of the play method. It can be initialized in the class constructor or at the highest level scope instead.

Answer №2

To address the symptoms caused by adding the event listener multiple times without removing it, there are several potential solutions:

  • One solution is to add the event listener just once, outside of the operational loop of play(), triggering an ended event. This can then be handled by listening for the event and calling play again from within the listener.

  • Another approach involves removing the previous event handler before adding a new one within the ended handler. While this method works, it adds complexity due to the necessity of maintaining a reference to the function returned by bind in order to remove it later.

  • An alternative strategy is to have the browser automatically remove the handler after execution by including {once: true} as the third argument of addEventListener when adding the event handler:

    this.player.addEventListener('ended', function () {
        // handler logic here
    }.bind(this), {once: true});
    

    It's important to consider browser compatibility when using this option, as it may not be supported in Internet Explorer.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Once the "Get Route" button is pressed, I want to save my JavaScript variable into a database

I am seeking to automatically extract data from the Google Maps API and store it in my MySQL database. Specifically, I want details such as source address, destination address, distance, and duration for all available routes to be inserted into my database ...

Fixing Bugs in Checkbox Functionality using useState in Reactjs when implementing Material UI

I am working on a numeric select functionality where selecting a number renders the component multiple times. Inside the component, there are checkboxes that should not all activate at once when one is selected. You can view the code in the sandbox: http ...

Having trouble locating the web element within a div popup while utilizing Node.js and WebdriverIO

I need assistance with a seemingly simple task. I am currently learning webdriverjs and attempted to write a short code to register for an account on the FitBit website at URL: www.fitbit.com/signup. After entering my email and password, a popup appears as ...

Click on every link to reveal a hidden div

When I click on and select the first link in the mainPart, I want to automatically select the first subLink div in the secondPart while hiding the other subLink classes. This sequence should be maintained: when the second link is selected, the second sub ...

Tips on utilizing Sinon for mocking a function that triggers a REST request

I'm currently navigating my way through sinon and mocha, working on the code and test provided below. My goal is to test the findAll() method without triggering an http request. However, I've encountered an error with the current setup: [TypeErr ...

Steps for creating a jQuery function that responds to changes in a text box value

Currently, I have a text box containing certain values and a submit button alongside a slider. When I click the submit button, the slider changes. However, I would like to achieve the functionality where instead of clicking the submit button, changing the ...

`Loading CSS and JS files in node.js: A step-by-step guide`

I've searched through numerous similar questions without success, so I'm reaching out for help. My folder structure looks like this: Source Code Frontend Graphs.html Graphs.css Temperature.js Server_Backend server.js I aim ...

I wish to adjust the font size as well as resize the table elements simultaneously

Adjusting the height and width of the table should automatically adjust the font size as well. <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>jQuery UI Resizable - Default functiona ...

A guide on accessing information from nested arrays in JavaScript

I am having trouble retrieving data from a JavaScript array as it keeps showing undefined. Here is the code snippet: sabhaDetailsArrayTemp.forEach(element => { let arra = []; console.log(element) //return tmp.m_category_name ; arra = this.onSa ...

Please upload JSON data into a database using Node.js

As a beginner in learning node.js, I have embarked on my "Hello World!" project. The premise is simple - I am requesting a JSON file from the server via an API and receiving a response that looks like this: { "files": [{ "url": "http://auction ...

How can one execute a function within an HTML attribute value using Angular?

I am currently attempting to use the weatherToFontAwesomeIcon(weatherDescription: string) function directly within the HTML file for this component. My goal is to showcase a specific FontAwesome icon based on the weather response from the API. import { Cur ...

Custom palette in Material UI design palette allows users to create

Hey there everyone! I've been working on a website using ReactJS and Material UI, starting with this cool template. One thing I'm trying to do is change the color of the TextField when it's focused. Right now it's blue, but I want it ...

Angular material is experiencing an issue where content is being cut off or

I am currently working on a project using AngularJS for a web application. I have encountered an issue where some of the content in the md-content element is being clipped. For instance, the body tag has the style: overflow: hidden, and the child md-conte ...

Obtaining the referring URL after being redirected from one webpage to another

I have multiple pages redirecting to dev.php using a PHP header. I am curious about the source of the redirection. <?php header(Location: dev.php); ?> I attempted to use <?php print "You entered using a link on ".$_SERVER["HTTP_REFERER"]; ?> ...

What is the best way to utilize the $('input').on('change', function() method within AngularJS?

I am working on creating a registration form page using AngularJS and I need to display the percentage completed. The form consists of over 50 fields, so I am looking for a simple way to implement this functionality. Below is a snippet of the code I have ...

Including a label for an array within an unnamed array in a JSON string

Is there a way to transform the following data: [{"name": "Donald"}, {"name": "George"}] Into this format instead: {MyArray: [{"name": "Donald"}, {"name": "George"}]} I am currently working on a database server that I built using node.js, express, an ...

Incorporate functionality into a button using jQuery

I am working on a table that displays data in different levels (Parent, Child, Grandson). When I click on the parent row, it expands to show new rows related to the child level. Similarly, clicking on a child row reveals a third level known as the grandson ...

Ways to extend div to fill the rest of the page's vertical space

Apologies, my search has yielded many results, but none that directly address my specific issue. It appears that there is a proliferation of div-height problems on this platform. :-( Here is the layout I am working with for testing purposes: <!DOCTYPE ...

Every time I attempt to build a React application, I encounter the same error message. I even checked the log file, but it keeps showing the proxy error

An error occurred in the command prompt while installing packages. This process may take a few minutes. Installing react, react-dom, and react-scripts with cra-template... Error: ERR_SOCKET_TIMEOUT The network encountered a socket timeout while trying to ...

How can I change the "Return" button on the iOS keyboard to a "Next" button using jQuery or JavaScript?

Currently, I am developing an HTML application and working on implementing it for IOS devices such as the IPAD. Within my application, there are multiple text boxes. Whenever a user clicks on a text box to input text, the keypad appears. On this keypad, ...