0

I have some code below to transform a fetched json into string and remove the braces and parse it into a map variable:

let result = '';
let map = [];

fetch(link)
  .then(function(response) {
    return response.json();
  }).then(function(json) {
    result = JSON.stringify(json); //json here is like [{'a':1,'a2':2},{'b':11,'b2':12}]
    result = result.substring(1, result.length - 1);
    map = JSON.parse(result);
  }).catch(function(ex) {
    console.log('parsing failed', ex);
  });

I've tried to simply set map=json but it both gives out the same error that I have duplicate keys for the map.

If I hard code my map variable to lets say [{'id':1,code: 007},{'id':2, code:014}] it works. I've tried to log result after changing it to a string and its exactly as the example. So in other words, setting map=json should work in the first place.

I think I might be missing something. What is it?

EDIT #1:

fetch(link)
.then(function(response) {
  return response.json();
}).then(function(json) {
  setData(json);
  document.getElementById("result").innerHTML = json;
}).catch(function(ex) {
  console.log('parsing failed', ex);
});


function setData(json) {
  map = json;
}

I've tried the solution given by Naomik except without the response ok part. I'm still receiving the same error as map = json. Any help with this?

Joshua Rajandiran
  • 2,788
  • 7
  • 26
  • 53
  • What does the `json` argument in the second `.then()` contain? Isn't it already a string? If you strip the square brackets off `[{'a':1,'a2':2},{'b':11,'b2':12}]`, which incidentally you can do more easily with `.slice(1,-1)`, you end up with something that isn't valid JSON. – nnnnnn Jul 01 '16 at 06:15
  • You're doing the same thing you just moved the `map = ...` to another function. You will **never** be able to access the data *outside* of the callback chain. Read ["How do I return the response from an asynchronous call?"](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) and ["Why is my variable unaltered after I modify it inside of a function?"](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Mulan Jul 01 '16 at 07:24
  • Those questions have hundreds of upvotes because they are extremely common. Understanding asynchronous programming is an uphill climb, but once you get the hang of it, it's easy. – Mulan Jul 01 '16 at 07:29
  • I'm still in the process of reading it, but I kind of understand the concept of asynchronous calls. Btw as I've mentioned in my post, setting `map` to a sample hard coded json data worked. Eg `map = [{"a":1},{"a":2}]` works but `map = json` doesn't work. Any ideas? – Joshua Rajandiran Jul 01 '16 at 08:24

1 Answers1

3

You can't set a variable like that in an asynchronous handler and expect it to be set outside of the handler. More about that here: "How do I return the response from an asynchronous call?"

I would've just marked your question as a duplicate of that one, but there's other issues with your code so I'm gonna address those now

In your second .then call, you are attempting to process json but you're doing it incorrectly

// Why exactly are you re-stringifying the data we just parsed ?
result = JSON.stringify(json);

// ... wtf ?
result = result.substring(1, result.length - 1);

// Same as above, any vars you set here cannot be read outside of the callback.
// This won't work like you expect (see the related question I linked above)
map = JSON.parse(result);

Remember, JSON is just a string that represents your data, nothing else

  • JSON.parse will take a json string and turn it into data.
  • JSON.stringify will take data and turn it into a json string.

This example might help you a bit

fetch(link).then(function(response) {
  if (response.ok)
    // read JSON response and parse it
    return response.json() 
  else
    // response is not OK, throw error
    throw Error(response.status + " " + response.statusText)
})
.then(function(data) {
  console.log("Your data has arrived!")
  console.log("Do something here with your data")
  doSomething(data)
})
.catch(function(err) {
  console.error(err.message)
})

function doSomething(data) {
  console.log("Here's your data:", data);
}
Community
  • 1
  • 1
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • FYI the OP uses https://github.com/github/fetch which already does all the parsing. Naming is unfortunate in the samples provided on the github page. – Tomalak Jul 01 '16 at 06:42
  • @Tomalak ah thanks. So it's safe to just pull out the `.then(json => JSON.parse(json)` and skip right to `.then(data => ...)` ? – Mulan Jul 01 '16 at 06:47
  • @Tomalak thanks. Yeah very unfortunate naming. That's definitely one of my biggest pet peeves; when someone names a var `json` that's not actually a JSON string. – Mulan Jul 01 '16 at 07:00
  • 1
    I was about to say the same thing. It really grinds my gears. ;) I had an answer ready that explained that (and the return-values-from-async-functions bit), but you beat me to it by a minute or so. – Tomalak Jul 01 '16 at 07:02
  • @naomik , I've tried your solution. See the edited part of my question. I'm still receiving the same errors – Joshua Rajandiran Jul 01 '16 at 07:23
  • Yes because you're still trying to set `map`. I already said you cannot do that. Read the questions I linked in the comment to your question. – Mulan Jul 01 '16 at 07:30