Blog>
Snippets

'this' in Asynchronous Code

Illustrate the challenges of using 'this' within an asynchronous function and how to address them.
<div id='button-container'>
  <button id='my-button'>Click Me</button>
</div>
HTML structure that contains a button.
#button-container {
  display: flex;
  justify-content: center;
  padding: 20px;
}

#my-button {
  padding: 10px 20px;
  cursor: pointer;
}
CSS to style the button container and the button itself.
// Example demonstrating the issues with 'this' in asynchronous code

class AsyncButtonHandler {
  constructor(buttonId) {
    this.button = document.getElementById(buttonId);
    this.button.addEventListener('click', this.handleClick.bind(this));
  }

  handleClick() {
    setTimeout(() => {
      // 'this' refers correctly to the AsyncButtonHandler instance due to arrow function
      console.log('Button clicked:', this.button.id);
    }, 1000);
  }
}

new AsyncButtonHandler('my-button');
JavaScript class handling button clicks. The 'handleClick' method sets up a timeout. Arrow function ensures 'this' refers to the class instance within the async code.
// Alternative approach using function binding

class AsyncButtonHandler2 {
  constructor(buttonId) {
    this.button = document.getElementById(buttonId);
    // Bind the handleClick method to current instance
    this.handleClick = this.handleClick.bind(this);
    this.button.addEventListener('click', this.handleClick);
  }

  handleClick() {
    setTimeout(function() {
      // 'this' refers to the AsyncButtonHandler2 instance as it is bound
      console.log('Button clicked:', this.button.id);
    }.bind(this), 1000);
  }
}

new AsyncButtonHandler2('my-button');
An alternative JavaScript class that uses function binding to ensure 'this' in asynchronous code refers to the class instance.