3

I'm using an AJAX call in a function to retrieve some data from the server, in this way:

getPolicies: function() {
  $.ajax({
    async: false, // wait for response
    type: "GET",
    url: "http://localhost:8080/getPolicies",
    contentType: "application/json",
    dataType: "json",
    success: function(jsonList) {
      for(var i in jsonList) {
        console.dir(jsonList[i].policyName);
      }
      return jsonList;
    },
    failure: function(err) {console.log("Error");}
  });
}

I correctly get the JSON array:

[ 
  { 
    "policyName": "policy1"
  },
  { 
    "policyName": "policy2"
  },
  { 
    "policyName": "policy3"
  }
]

This JSON array is returned by the function. But when I call the function getPolicies() I only get an empty JSON object {}. Specifically, if i try

var policies = getPolicies();
console.log(policies[1].policyName);

I get this:

Uncaught TypeError: Cannot read property 'policyName' of undefined

So, how is possible that even if I correctly get the JSON array, the function returns an empty object?! Thanks...

Marco
  • 700
  • 1
  • 14
  • 26
  • Yes, actually it's addressing more or less the same problem... Sorry, I didn't get it before! – Marco May 12 '14 at 11:14

1 Answers1

5

Even though the AJAX request is synchronous *), the return statement still returns only from the success handler. Try something like this:

getPolicies: function() {
  // Declare variable here
  var resultList = null;

  $.ajax({
    async: false, // wait for response
    type: "GET",
    url: "http://localhost:8080/getPolicies",
    contentType: "application/json",
    dataType: "json",
    success: function(jsonList) {
      for(var i in jsonList) {
        console.dir(jsonList[i].policyName);
      }
      // Set the variable in the scope of getPolicies.
      resultList = jsonList;
    },
    failure: function(err) {console.log("Error");}
  });

  // This one actually returns getPolicies
  return resultList;
}

But in general, it's regarded bad practice to make AJAX calls synchronous. Instead, you can better call the necessary functionality from the success handler. That can also be another function. For instance, you can declare

function processPolicies(policies)
{
  console.log(policies[1].policyName);
}

And your call handler can look like this (:

$.ajax({
  async: true, // just let it run,
  type: "GET",
  url: "http://localhost:8080/getPolicies",
  contentType: "application/json",
  dataType: "json",
  success: function(jsonList) {
      processPolicies(jsonList);
  },
  ...

*) The first A even stands for Asynchronous. But on the other hand, the X stands for XML, so what you're doing here should actually be called JaJ rather than AJAX. ;)

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • FYI you shouldn't ever use `async` false. From the API: `As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().` – Rory McCrossan May 12 '14 at 09:36