1

I'm having some issues understanding variables and functions using fetch. I'm trying to pass the value of response from

.then(response => response.json())

to

.then(lang => response['lang'].slice(-2)

But I am getting the undefined variable response error, so I'm not referencing the variable correctly. What's the correct way of calling it?

Also I want to call both console logs, the piece of code below currently does that but I don't think I should be overwriting response function, can I call a function without arguments or the commands by themselves?

.then(response => console.log(response['text']) & console.log(food))

console.log(response['text']) & console.log(food)

  fetch("https://localhost:8000", {method:"POST", body:fd})
  .then(response => response.json())
  .then(lang => response['lang'].slice(-2))
  .then(food => "Temporary")
  .then(function detectType(lang) {
  switch(lang) {
    case 'abc':
        food = "Bananas";
        break;
    case 'def':
        food = "Apples";
        break;
    default:
        food = "Bananas";
        break;
   }})
  .then(response => console.log(response['text']) & console.log(food))
  .catch(err => console.error(err));
}
Juanvulcano
  • 1,354
  • 3
  • 26
  • 44
  • Why did you name the parameter of the function `lang`? You are not doing anything with it. It should be `.then(response => response['lang'].slice(-2))` (but it doesn't matter what you call the parameter). Parameters are only accessible in the function they are defined in. See also [What is the scope of variables in JavaScript?](https://stackoverflow.com/q/500431/218196) – Felix Kling May 31 '17 at 20:34
  • If I do that to the parameter, then what would happen when I try to call response['text']? This is a json dictionary with kind of {'text':'a', 'lang':'b'} – Juanvulcano May 31 '17 at 20:38
  • If by "call" you simply mean "access", it will return the string `'a'`. Example: `var foo = {text: 'a'}; console.log(foo['text']);`. – Felix Kling May 31 '17 at 20:38
  • No, I mean look at: `console.log(response['text']) & console.log(food)`. If I do `.then(response => response['lang'].slice(-2))`, won't the response that is currently `{'text':'a', 'lang':'bbb'}` become only 'b'? @FelixKling – Juanvulcano May 31 '17 at 20:43
  • Of course. But if you don't want that then the problem is not with the parameter name but with what the function does. All the `.then`s are *chained*. The next `.then` callback receives whatever the previous callback returns. The parameter names having nothing to do with each other (i.e. `response` in `.then(response => console.log(response['text']) & console.log(food))` has nothing to do with `.then(response => response.json())`. Again, parameters are scoped the functions. Here is a simplified example of your problem: `function foo(bar) { }; foo(42); console.log(bar);`... – Felix Kling May 31 '17 at 20:47
  • ... you cannot access `bar` outside of the function because it is only defined inside the function. `food` is not defined in the second to last function call. Do you know how functions work in general? Promises don't change how functions work. Take a step back and remember the basics about functions. – Felix Kling May 31 '17 at 20:48

2 Answers2

2

If I'm understanding what you want to do, keep in mind that the return value of one function is the state received by the next function. So you'd be looking to do something more like this:

fetch("https://localhost:8000", {method:"POST", body:fd})
  .then(response => response.json())
  .then(response => {
    response['lang'] = response['lang'].slice(-2);
    return response;
  })
  .then(response => {
    response['food'] = "Temporary";
    return response;
  })
  .then(function detectType(response) {
    switch(response['lang']) {
      case 'abc':
          response['food'] = "Bananas";
          break;
      case 'def':
          response['food'] = "Apples";
          break;
      default:
          response['food'] = "Bananas";
          break;
     }
    return response;
  })
  .then(response => {
    console.log(response['text']);
    console.log(response['food']);
  })
  .catch(err => console.error(err));
}
Brett Beatty
  • 5,690
  • 1
  • 23
  • 37
2

Regarding fetch(), remember that it is very 'Promise heavy'.

fetch("https://localhost:8000", {method:"POST", body:fd}) returns a Promise, which you handle with the first then()

then(response => response.json()) returning response.json() will give you the state of response.json() in the next .then(). So, you have access to the JSON representation of the response by the next then().

Let's take a look at how it should look:

fetch("https://localhost:8000", {method:"POST", body:fd}) 
  .then(response => response.json()) 
  .then(jsonResp => jsonResp['lang'] ); 

By that last line, you can check the JSON object and its keys without going down a Promise chain. If you want to check the lang attribute, you have access to it the way it's seen on the example.

Hope this helps!

Sammy I.
  • 2,523
  • 4
  • 29
  • 49
  • *"since `response.json()` returns a Promise"* No, that's not the reason. `.then` *always* returns a promise. Maybe you mean that the *callback* returns a promise? In that case you are right. – Felix Kling Jun 01 '17 at 03:35
  • Got it, fixed it. Thank you! – Sammy I. Jun 03 '17 at 05:37