0

Okay, I think I may be retarded, but I can't figure this out for some reason.

I have this code.

var x = [];

$.getJSON('data.json', function(data) { 
    $.each(data, function(key, val) {
        x.push(val);
    });
});

console.log(x);

It prints this to console.

output

I cannot for the life of me figure out how to access x or y. Can someone explain to me how this works?

json:

[
 {
   "x": 121.87375,
   "y": 483.7810417
 },
 {
   "x": 116.831875,
   "y": 471.9985417
 },
 {
   "x": 111.694375,
   "y": 460.0341667
 }
]

I just want to be able to do a for loop and update x and y to the next index every second.

Ryan Deming
  • 63
  • 1
  • 7
  • instead of link post an image together with the OP – guradio Apr 18 '17 at 04:02
  • Please [edit] your question to show what the content of `data.json` is, and what the corresponding desired output of your JS is. For the `x` array that you show that was logged in the console, you could say `x[0].x` and `x[0].y` to get the coordinates of the first item in the array. – nnnnnn Apr 18 '17 at 04:03
  • 1
    Your `console.log` is happening before the XHR request comes back, which is why it is printing an empty array. Move the `console.log` into the callback, after the `$.each` loop. – Useless Code Apr 18 '17 at 04:05
  • 1
    Related: [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Jonathan Lonowski Apr 18 '17 at 04:06
  • @nnnnnn I tried x[0].x it gives a cannot read property of undefined. Basically the x array is always undefined. – Ryan Deming Apr 18 '17 at 04:08
  • @UselessCode I want to be able to access the data outside of the get json. More specifically I want to loop through each index and update x and y every second. Is this possible or does it have to be within the getjson? – Ryan Deming Apr 18 '17 at 04:09
  • It's undefined because of what Jonathan's link explained about async code. – nnnnnn Apr 18 '17 at 04:10
  • Oh. I just gave it a setTimeout of 1000ms and it worked fine. Guess I'm retarded. Thanks. – Ryan Deming Apr 18 '17 at 04:14
  • 2
    No, don't just delay your other code with `setTimeout()` - what if you have a slow connection and it takes 1200ms for the Ajax to run, or 2200ms? Code that needs the results should either be in the `$.getJSON()` callback or called from there. (Or you could restructure a bit to use promises instead.) – nnnnnn Apr 18 '17 at 04:18
  • I'm not familiar with promises. Is that a way to execute code after the ajax is confirmed to be finished? – Ryan Deming Apr 18 '17 at 04:35
  • I added .done(function() { } and added my code inside there and it seems to work. Is that more correct? – Ryan Deming Apr 18 '17 at 04:41

2 Answers2

0

$.getJSON is asynchronous, the data is not inside of x when you call console.log immediately after you make the getJSON call. You have to wait for the network request to finish before you can use the data it is retrieving.

There are a couple of ways you could make it work. The traditional approach would be to use data inside of the callback after you receive it by moving console.log there:

var jsonData = [{"x": 121.87375,"y": 483.7810417},{"x": 116.831875,"y": 471.9985417},{"x": 111.694375,"y": 460.0341667}];
$.getJSON = function fakeGetJSON (url, callback) {
  setTimeout(callback.bind(null, jsonData), 500);
};

var x = [];

$.getJSON('data.json', function(data) {
  $.each(data, function(key, val) {
      x.push(val);
  });
  console.log(x);
  // call another function that uses x, etc.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

The second would be to use a Promise. jQuery AJAX calls return a jqXHR object. As of version 3.0 the jqXHR object is compatible with the Promises/A+ standard. If you are using a version before 3.0, you'll have to use .done instead of .then.

var jsonData = [{"x": 121.87375,"y": 483.7810417},{"x": 116.831875,"y": 471.9985417},{"x": 111.694375,"y": 460.0341667}];
$.getJSON = function fakeGetJSON (url, callback) {
  return new Promise(function(resolve, reject) {
    setTimeout(function () {resolve(jsonData)}, 500);
  });
};

var x = [];

$.getJSON('data.json').then(function(data) {
  $.each(data, function(key, val) {
      x.push(val);
  });
  console.log(x);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

You could also write it like this:

var jsonData = [{"x": 121.87375,"y": 483.7810417},{"x": 116.831875,"y": 471.9985417},{"x": 111.694375,"y": 460.0341667}];
$.getJSON = function fakeGetJSON (url, callback) {
  return new Promise(function(resolve, reject) {
    setTimeout(function () {resolve(jsonData)}, 500);
  });
};

var x = [];

var dataPromise = $.getJSON('data.json').then(function(data) {
  $.each(data, function(key, val) {
      x.push(val);
  });
  return x;
});

dataPromise.then(function (data) {
  console.log(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

It should also be noted that unless you are doing more complicated processing in your real code, you don't need to loop over the data with $.each, the data that is being returned is already an array of objects:

var jsonData = [{"x": 121.87375,"y": 483.7810417},{"x": 116.831875,"y": 471.9985417},{"x": 111.694375,"y": 460.0341667}];
$.getJSON = function fakeGetJSON (url, callback) {
  setTimeout(callback.bind(null, jsonData), 500);
};

var x = [];

$.getJSON('data.json', function(data) {
  x = data;
  console.log(x);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Useless Code
  • 12,123
  • 5
  • 35
  • 40
0

Some Clarifications :

  1. JSON you are getting in console is already having an array of objects. What else you needed ?
  2. If you want to access the value of x and y from the JSON then you can use JavaScript map() or for..in loop methods to iterate the array object.

Using map()

var jsonObj = [
 {
   "x": 121.87375,
   "y": 483.7810417
 },
 {
   "x": 116.831875,
   "y": 471.9985417
 },
 {
   "x": 111.694375,
   "y": 460.0341667
 }
];

var res = jsonObj.map(function(item) {
  return item.x;
});

console.log(res);

Using for...in loop

var jsonObj = [
 {
   "x": 121.87375,
   "y": 483.7810417
 },
 {
   "x": 116.831875,
   "y": 471.9985417
 },
 {
   "x": 111.694375,
   "y": 460.0341667
 }
];

for(var i in jsonObj) {
  console.log(jsonObj[i].x);
}
Debug Diva
  • 26,058
  • 13
  • 70
  • 123