0

Possible Duplicate:
Return Value from inside of $.ajax() function

I'm working on a CakePHP app that makes use of widespread AJAX calls to controllers. I'm stuck with one particular AJAX call in which I'm trying to assign the response from the controller to a JS global variable. Here is the code:

window.errors = "";

function setErrors(err) {
    window.errors = err;
}

function ajaxCall(u, t, d, dt) {
    var type = typeof t !== 'undefined' ? t : "post";
    var dataType = typeof dt !== 'undefined' ? dt : "json";
    var success = false;
    var err = "";
    $.ajax({url: url, data: "data=" + d, type: type, dataType: dataType,
        success: function(d){
                if(d.hasOwnProperty('success') === false) { //json response
                    for(var i in d) { //fetch validation errors from object
                        for(var j in i) {
                            if(typeof d[i][j] === "undefined") {
                                continue;
                            }
                            err += d[i][j] + "<br/>";
                        }
                    }
                    console.log(err); //<=== displays correct value
                    setErrors(err); //<=== but somehow this seems to be failing??
                }
                else {
                   if(d.success === "1") {
                       success = true;
                }
            }
        }
    });
    return success; //<=== I suspect this might be the culprit
}

And this is how ajaxCall() is used:

function register() {
    var data = {};
    var $inputs = $("#regForm :input");
    $inputs.each(function(){
        data[this.name] = $(this).val();
    });
    data = {"User" : data }; //CakePHP compatible object
    data = JSON.stringify(data);

    //Here's the AJAX call
    if(ajaxCall('https://localhost/users/add', 'post', data, 'json')) {
        alert("Registered!");
    }
    else {
        alert(window.errors); // <=== empty string
        console.log("window.errors is: " + window.errors); // <=== empty string
    }
}

But on the Chrome JS console, window.errors returns the correct value (non-empty, validation error string).

I found a similar question that possibly might be addressing my issue (the return success immediately following the $.ajax() is being executed before the success: callback). How can I fix this without drastically changing the code (also, I don't want to make this a synchronous call)?

Community
  • 1
  • 1
Agent.Logic_
  • 1,553
  • 2
  • 25
  • 36

1 Answers1

0

Yes, you are right that the return statement runs before the success callback. You can't return the result from the function, as the function has to return before the success event can be handled.

Add a callback to the ajaxCall function, and call that instead of setting the success variable:

function ajaxCall(u, t, d, dt, callback) {
  var type = typeof t !== 'undefined' ? t : "post";
  var dataType = typeof dt !== 'undefined' ? dt : "json";
  $.ajax({url: url, data: "data=" + d, type: type, dataType: dataType,
    success: function(d){
      if(d.hasOwnProperty('success') === false) { //json response
        for(var i in d) { //fetch validation errors from object
          for(var j in i) {
            if(typeof d[i][j] === "undefined") {
              continue;
            }
            err += d[i][j] + "<br/>";
          }
        }
        callback(false, err);
      } else {
        callback(d.success === "1", "");
      }
    }
  });
}

Send the code for handling the result into the ajaxCall function:

ajaxCall('https://localhost/users/add', 'post', data, 'json', function(success, err){
  if (success) {
    alert("Registered!");
  } else {
    alert(err);
  }
});
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Thank you for your quick reply! Yes, your solution worked perfectly. I'm learning quite a few new JS stuff (and many of its quirks) the more I work with it. – Agent.Logic_ Sep 03 '12 at 15:35