-1

My first function gets a JSON array object via a jQuery AJAX request. My second function tries to access the object, but is hit with a "jQuery.Deferred exception: Unable to get property '1' of undefined or null reference..." (Note '1' refers to my trying to access oJSON[1].name as shown in the following code.)

Here is my JSON:

[{"name":"Alpha", "numWalks":1},{"name":"Beta","numWalks":2}]

Here is my code: (Note: I have to save the JSON as a .txt file and parse it to JSON because of how my SharePoint site is set up.)

var oJSON;
$("document").ready(function() {
  getText().done(getDogs());
});

function getText() {
  var deferred = $.Deferred();
  $.get("dogWalksJSON.txt", function(returnedText) {
    oJSON = JSON.parse(returnedText);
  });
  deferred.resolve();
  return deferred.promise();
}

function getDogs() {
  console.log(oJSON[1].name);
}

If I console.log(oJSON[1].name) in the getText() function, it works. But when I try to access that info from the getDogs() function, I get the exception. My guess is that it's trying to access the info before it's ready (if I try to access it from my browser's console, it works), which is why I added the defer/promise.

Anyone have any suggestions to how I can fix this?

Thanks!

JohnS
  • 23
  • 7
  • 1
    `done(getDogs())` calls `getDogs` immediately, then calls the result of `getDogs()` when `getText()` is done. You likely want `done(getDogs)`. – Heretic Monkey Jul 28 '17 at 15:05
  • Avoid the [deferred antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! And you're calling `deferred.resolve()` too early anyway. – Bergi Jul 28 '17 at 15:17

1 Answers1

-1

My guess is that it's trying to access the info before it's ready

Indeed. You're calling deferred.resolve too early, and you're calling getDogs() immediately instead of passing it into then.

Avoid the deferred antipattern and the global oJSON variable, use

$("document").ready(function() {
  getText().then(getDogs  );
//                      ^^ no call
});

function getText() {
  return $.get("dogWalksJSON.txt")
  .then(function(returnedText) { // chain the promise
    return JSON.parse(returnedText); // fulfill it with the parsed object
  });
}

function getDogs(oJSON) {
  console.log(oJSON[1].name);
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • That worked! But would you be able to explain how the oJSON is being passed to the getDogs() function? Is it because it's the end result of the getText() function and is being returned and then automatically passed to the .done(getDogs); call? Also, if I then want to start making calculations based on my JSON data, do I need to keep stringing .done methods together or can I just put my next function call under the original getText() call? – JohnS Jul 28 '17 at 15:54
  • @JohnS Yes, it's the result value of the promise returned by `getText`. – Bergi Jul 28 '17 at 15:59
  • @JohnS Yes, you'd need to chain further handlers, but you should use `then` and never `done` – Bergi Jul 28 '17 at 16:00