3

I would like to know, how do I do in order to call a function in a promise in a fetch?

Please note this line: .then(json => this.processReq(json))

I have to use this. because if don't it says that processReq is undefined. Shouldn't it be something like: .then(json => processReq(json)) because of ES6 ??

this is my code (I'm using Babel ES6 and React):

import React, { Component, PropTypes } from 'react'
import fetch from 'isomorphic-fetch'

export default class Batchprodpry extends Component {
  constructor(props) {
    super(props) {
  .
  .
  .
  processReq(json) {
    Object.keys(json).forEach(item => {
      if (item === 'error') {
        Object.keys(json[item]).forEach(propry => {
          alert('Conflicto! '+'\n'+
            'Id: ' + JSON.stringify(json[item][propry]['propryid'])+'\n'+
            'Id Operador: ' + JSON.stringify(json[item][propry]['fkempid'])+'\n'+
            'Hora inicio: ' + JSON.stringify(json[item][propry]['propryhoraini'])+'\n'+
            'Hora fin: ' + JSON.stringify(json[item][propry]['propryhorafin']))          
        })
      }
    })
  }
  .
  .

  postForm() {
    let maq = this.state.obj['fkmaqid']
    return fetch(`/scamp/index.php/batchprodpry/${maq}`, {
      method: 'POST',
      credentials: 'same-origin',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(this.state.a)
    })
    .then(req => {
      if (req.status >= 400) {
        throw new Error("Bad response from server")
      }
      return req.json()
    })
    .then(json => this.processReq(json))
    .catch(function(error) {
      console.log('request failed', error)
    })
  }
Rafael Mora
  • 1,095
  • 2
  • 13
  • 21
  • 1
    "*Shouldn't it be something like […] because of ES6 ??*" - No, why would it? `processReq` is still a method of the instance. – Bergi Aug 07 '16 at 14:37
  • I updated my question – Rafael Mora Aug 07 '16 at 16:06
  • 2
    after your update, `processReq` is still an instance method, not a local variable. local variables are declared only with the keywords `var` and `let`, you are using the ES6 syntax how to define methods that are referenced by `this` – Aprillion Aug 07 '16 at 16:07

1 Answers1

6

No.

Using a ES6 fat-arrow function means that this is bound to something else than the body of the function at hand.

If you used the ES5 syntax to express a similar function, this would be bound to the body of function and this.processReq would be undefined:

function (json) {
  return this.processReq(json);  // undefined
}

So an ES5 equivalent would have to be:

var self = this;
return fetch(...)
  .then(function (json) {
    return self.processReq(json);
  });

As it happens in your particular example, this refers to the instance of Batchprodpry class. There is no local function with name processReq, only a method defined for the class instance.

Aprillion
  • 21,510
  • 5
  • 55
  • 89
  • So, in promises the functions calls without `this.` are referred to local, and even that I'm using ES6 with arrows I still must use `this.` ?? – Rafael Mora Aug 07 '16 at 16:03
  • 1
    because you are using ES6, you **can** use `this` - in ES5 it would be useless – Aprillion Aug 07 '16 at 16:06
  • So in conclusion, promises **can** use local calls and they **need** `this.` for calling class methods. Thank you guys! – Rafael Mora Aug 07 '16 at 16:12
  • I did something like this: `() => { statements }` and I didn't work – Rafael Mora Aug 07 '16 at 16:21
  • 1
    well, the difference between lexical scope used in `=>` and dynamic scope used in `function` is mostly about the binding of `this` - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions for a good documentation. not related to `Promise` per se, but the at the time when a function gets executed, the values of the closure variables might have changed from what you *think* they ought to be – Aprillion Aug 07 '16 at 16:23
  • 1
    what didn't work? did you `return` anything or the statements were supposed to execute some side effect and didn't? I recommend to add a `console.log(variable_of_interest)` a then ask new question with the details of what exactly is "not working" – Aprillion Aug 07 '16 at 16:26
  • uh, what? did you define a function and never executed it? and you removed the `return` statement from inside the `postForm` method? was there any actual reason to poke your code with a hot stick like that? – Aprillion Aug 07 '16 at 17:16
  • I did not define a function, I tried to invoke the method `processReq` without the `this.`. Like this: `postForm() { let maq = this.state.obj['fkmaqid'] () => { return fetch(url, { .....` – Rafael Mora Aug 07 '16 at 17:21
  • I thought that with using of the `=>` I wouldn't have to use `this.` ever again, now I know that I was **wrong** – Rafael Mora Aug 07 '16 at 17:25
  • I use the method `processReq` in order to process the json I get from the REST call – Rafael Mora Aug 07 '16 at 17:27
  • 1
    @RafaelMora: This has nothing to do with promises. It's just ordinary method calls and callbacks [with the same old problem](http://stackoverflow.com/q/20279484/1048572) that *arrow functions* solve in ES6. – Bergi Aug 07 '16 at 18:05
  • @Bergi and that's the origin of my post, why if I'm using arrow function I still need to write `this.` in order to call the method `processReq` ? – Rafael Mora Aug 07 '16 at 18:08
  • 2
    @RafaelMora: The arrow function does not make `this` go away. It changes its value to make it work in the first place. With a normal function, you had to use `this` and `bind`! – Bergi Aug 07 '16 at 21:55
  • @Bergi perfect! Thanks for your help – Rafael Mora Aug 07 '16 at 22:42
  • @Bergi I mentioned promises as I thought that somehow as they async they doesn't get the vars and functions where they reside making the use of `this.` a must – Rafael Mora Aug 07 '16 at 22:44
  • 1
    @RafaelMora: No, promise `then` callbacks are standard closures, they do get any lexically scoped variables and functions. Like everywhere else, they [don't get *methods* without `this.`](http://stackoverflow.com/q/13418669/1048572?javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object). – Bergi Aug 07 '16 at 23:01