13

I'm sure you know this problem, I'm still trying to solve it for few days. I've tried lots of stuff but no one worked:

Here is the code

function lobbyLeader() {
    $.ajax({
       data: {"id": 1, "request": "lobbyinfo", "method": "read"},
       url: 'api.php',
       dataType: 'json',
       success: function(data){
           result = data.leader;
           return result;
       }
   });
}

alert(result); will show 1 but when using in an other function it says undefined.

Alexander
  • 23,432
  • 11
  • 63
  • 73
Nightbox
  • 165
  • 1
  • 2
  • 9

5 Answers5

17

You can't return from an asynchronous function like this, you're returning from that success callback function, not the parent function. Instead, kick off whatever you need in the callback, like this:

function lobbyLeader() {
  $.ajax({
    data: {"id": 1, "request": "lobbyinfo", "method": "read"},
    url: 'api.php',
    dataType: 'json',
    success: function(data){
      someOtherFunc(data.leader);
   }
 });
}
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
8

Correctly stated that you can't really return from the Success, however, if you are doing what I think you are doing, and that is to grab the data and return it and assign it to something in another area IE

var obj = lobbyLeader();

Then you can just set the function to async:false and return the obj outside of the Success after the code has finished running. example

function lobbyLeader() {
var obj;
  $.ajax({
    async:false;
    data: {"id": 1, "request": "lobbyinfo", "method": "read"},
    url: 'api.php',
    dataType: 'json',
    success: function(data){
      obj= JSON.parse(data);
   }
 });
    return obj;
}

This way the script stops to wait for success and then sets and returns.

matt
  • 91
  • 1
  • 1
  • "As of jQuery 1.8 [three years ago!] 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()." http://api.jquery.com/jQuery.ajax/ Promises aren't that hard to learn, it's worth the effort. Certainly an improvement on just blocking your whole UI until the request completes. – Daniel Beck Mar 31 '16 at 20:47
  • I faced the very same problem. You saved my day @matt. Also I did not set the function to `async:false` and got the correct output. – nightrain Mar 12 '20 at 22:34
5

The problem here is that AJAX is asynchronous (it's what the first A stands for). This means that the function returns immediately; the success handler is only called when the request is successful. This means that lobbyLeader returns immediately after you have made your request, so returns nothing.

If you have any code that needs to run after you have received the data, it must be placed in the success handler (or another AJAX event handler) or be invoked by it.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
3

I recommend this way.

  1. use the ajax call by the async:false.
  2. move the return statement after the ajax call.

Example :

function makeJQGridDataFromList(url)
{
    var rowData;
    var viewPage = 0;
    var viewTotal = 0;
    var viewRecords = 0;

    var resultObject;

    $.ajax({    
        type:"GET",
        url:url,    
        async: false,
        success:function(args){ 
            if(args.result==true)
            {
                try
                {
                    viewPage = args.cond.pageIndex;
                    viewTotal = args.cond.recordCountPerPage;
                    viewRecords = args.cond.totalCnt;

                    rowData = jsonMakeRowsForGrid(args.data);
                }
                catch (e)
                {
                    console.debug("Error!");
                    alert("Invalid data");
                    return;
                }
            } else
            {
                alert("API return ERROR!");
                return;
            }
        }, 
        error:function(e){
            alert("Fail AJAX communication");
            return;
        }
    });

    resultObject = {
        page : viewPage,
        total : viewTotal,
        records : viewRecords,
        rows : rowData
    };

    return(resultObject);
}

You can test the following method.

(In the other file (html or js))

var gridData = makeJQGridDataFromList(openAPIUrl);
console.debug(">> " + JSON.stringify(gridData));

You can see the gridData.

I faced same problems. :)

mass
  • 71
  • 4
1

When you return values from within an anonymous function that is executed asynchronously, those values will not propogate up the scope chain, the return statement is only applied on the current function scope, not the surrounding scope, $.ajax() is asynchronous, so immediately after executing the statement, the outer function returns, so there is no return value of the outer function, that's why you're getting undefined.

The only way to hook into a possible return value from the callback function passed to $.ajax is to invoke another outer function, passing in the desired data.

Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320