Search code examples
javascriptecmascript-6es6-promise

How to access class instance calling ES6 Promise within .then()?


I'm trying to resolve this in a Promise and can't figure out why it's not working. An arrow function usually does it for me, but this is a bit more convoluted than usual.

The snippet below, for example, gives the following error:

TypeError: Cannot read property 'processResponse' of undefined

Where is this getting lost?

If the snippet below doesn't work, try this codepen.

class Page {
  init() {
    this.datatable = new Datatable();
    this.datatable.setBehavior(this.behaviorFlavor)
  }

  behaviorFlavor() {
    console.log('Doing action...');
    Ajax.get()
      // 'this' is undefined
      .then((data) => { this.processResponse(data) });
  }

  processResponse(data) {
    console.log('Processing response...');
  }
}

class Datatable {
  setBehavior(callback) {
    // Add event listener to rows, etc.
    $('button').click(() => {
      callback();
    });
  }
}

class Ajax {
  static get() {
    return new Promise(function(resolve, reject) {
      console.log("Sending request...");
      resolve();
    })
  }
}

(new Page).init();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <button>Click Here!</button>
  <p>Then check your browser's console to see the error.</p>
</div>


Solution

  • The this context is getting lost by passing the behaviorFlavor function reference as a callback. You're basically extracting the method from its class and attempting to execute it in isolation.

    Try one of these alternatives...

    1. Use an arrow function to lock-in the this context

      setBehavior(() => { this.behaviorFlavor() })
      
    2. Directly bind the behaviorFlavor function

      setBehavior(this.behaviorFlavor.bind(this))