0

I am converting some code to ES6, and in one part I am trying to understand fat arrow binding. I had code like this:

function callApi(api, payload, header) {
    $http.post(api, payload, header)
    .success(function(data) {...})
    .error(function (data, status) { handleError(data, status) })
}

function handleError(data, status) {...}

I have changed that to this, which works:

callApi(api, payload, header) {
    this.$http.post(api, payload, header)
    .success((data) => {...})
    .error((data, status) => this.handleError(data, status))
}

handleError(data, status) {...}

What doesn't work is when I tried to call handleError like this:

.error((data, status) => this.handleError)

I thought that might be delegating the error handling to the handleError function, but it doesn't. Can someone help me understand what I'm misunderstanding about arrow binding that it can't be used like ()=>myFunction, and is there a way to do delegation like this that incorporates binding this?

Kip
  • 560
  • 7
  • 16
  • `(a, b) => c` is the same as `function(a, b){return c}.bind(this)` – elclanrs Aug 12 '15 at 20:52
  • 1
    it should just be `.error(handleError)` no need for ES6 for that to work correctly. – zzzzBov Aug 12 '15 at 20:56
  • `.error(handleError) ` results in "handleError not defined". `.error(this.handleError)` rsesults in an error inside handleError when I try to use `this` that `this` is undefined. – Kip Aug 12 '15 at 21:00
  • 1
    `.error(this.handleError.bind(this))` – elclanrs Aug 12 '15 at 21:01
  • Thanks, this worked: `error(this.handleError.bind(this))` Can I mark a comment as the accepted answer? – Kip Aug 12 '15 at 21:02
  • How about these answers? They go in more detail on the usage of `bind`. http://stackoverflow.com/questions/2236747/use-of-the-javascript-bind-method, http://stackoverflow.com/questions/15287925/mastering-javascript-function-bind – elclanrs Aug 12 '15 at 21:08
  • @Kip: Can you show us the implementation of `handleError` please, especially how it uses `this`? – Bergi Aug 12 '15 at 21:17

2 Answers2

2

I have changed that to (data, status) => this.handleError(…) which works

I'm worried if both handleError and this.handleError work. This could suggest that you have placed them in the global scope and are calling your functions without a receiver. I'd suggest to call the direct reference (only handleError(…)) and use strict mode (which becomes default with ES6 anyway).

What doesn't work is when I tried to call handleError like this: (data, status) => this.handleError

Well, simple: you're not calling it here, you've written an arrow function that returns the handleError function.

You should be able to simplify your code though by not using an arrow function at all:

callApi(api, payload, header) {
    this.$http.post(api, payload, header)
    .success((data) => {...})
    .error(handleError)
}

Or if handleError is a method of this though and relies on being called on the instance, you'd use .bind():

….error(this.handleError.bind(this));

In that case, your original ES5 should not have worked however?!

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks. @elclanrs said something similar above. This worked for me: `.error(this.handleError.bind(this))` – Kip Aug 12 '15 at 21:20
0

The this value for an arrow function is the this of the containing function. It doesn't create it's own this.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Lexical_this

Joseph
  • 117,725
  • 30
  • 181
  • 234