4

Possible Duplicate:
jQuery Ajax always returns “undefined”?

I'm trying to come up with a generic jquery ajax function which takes the url & parameters and returns the result. I'm trying to avoid using async:false as it locks up the browser. If I use success callback in the ajax call, the data returned is null due to the timing issue (success doesn't wait until the data is returned). If I use complete, the persons object is still null in the LoadPersons method as it doesn't wait for the data to be returned from the ajax call. If place an alert(persons) in the complete callback, I get [object][Object] so I'm getting the data back. How do I "fix" this issue? Am I talking sense? I would also ideally like to show a "loading.." image while it's doing this.

Here's my code -

  <script type="text/javascript">
    $(function() {
                var persons;
                var urlGetPersons = "Default.aspx/GetPersons";

                LoadPersons();

                function LoadPersons() {
                    persons = CallMethod(urlGetPersons, { });
                    if (persons != null) {
                        // do something with persons.
                    }
                }

                function CallMethod(url, parameters) {
                    var data;
                    $.ajax({
                        type: 'POST',
                        url: url,
                        data: JSON.stringify(parameters),
                        contentType: 'application/json;',
                        dataType: 'json',
                        success: function(result) {
                            data = result.d;
                        }, // use success?
                        complete: function(result) {
                            data = result.d;
                        } // or use complete?
                    });
                    return data;
                }
            });
   </script>
Community
  • 1
  • 1
tempid
  • 7,838
  • 28
  • 71
  • 101
  • 1
    `I'm trying to come up with a generic jquery ajax function which takes the url & parameters and returns the result` Isn't that what `$.ajax()` is anyway? – Rory McCrossan Feb 18 '12 at 00:10
  • I understand. I'm just trying to come up with a shorthand. I know I can use `.ajaxSetup` and setup the defaults but it's still going to take a couple of lines to write the actual function. – tempid Feb 18 '12 at 00:12
  • 1
    Such function cannot return the result synchronously without locking the browser, that's why ajax is asynchronous. Javascript has nothing else to do but to hang while the server comes back with a response. – Diego Feb 18 '12 at 00:13

3 Answers3

19

This is what's comes to my mind with "generic" - but it's still asynchronous:

function CallMethod(url, parameters, successCallback) {
                //show loading... image

                $.ajax({
                    type: 'POST',
                    url: url,
                    data: JSON.stringify(parameters),
                    contentType: 'application/json;',
                    dataType: 'json',
                    success: successCallback,
                    error: function(xhr, textStatus, errorThrown) {
                        console.log('error');
                    }
                });
            }

CallMethod(url, pars, onSuccess);

function onSuccess(param) {
    //remove loading... image
    //do something with the response
}
User
  • 31,811
  • 40
  • 131
  • 232
  • Thank you. It does seem like less code. Should I not use `complete` instead of `success`? I thought Success will just invoke the method and come back where as Complete gets returned until the server-side processing has been completed. – tempid Feb 18 '12 at 00:29
  • Only diffrence is, that `complete` is triggered after `success`. A callback function is the only solution that comes to my mind. If it still doesn't work try some debugging like `function onSuccess(param) { if(param == null) { alert('no result'); } else if(!param.hasOwnProperty('d')) { alert(typeof param); } else { // whatever } }` – Julien Schmidt Feb 18 '12 at 00:32
  • Can I combine `CallMethod` and `function onSuccess {}`? Something like `CallMethod(url, pars, function () { });` just so I don't have to write another function? I want everything as compact as possible. – tempid Feb 18 '12 at 00:32
  • Both complete and success wait for server's response. Here for example are more details: http://stackoverflow.com/questions/5240876/difference-between-success-and-complete. To the second question, yes, you can pass an anonymous function as parameter. – User Feb 18 '12 at 00:33
  • Thank you. So I did something like this - `var persons; CallMethod(url, pars, function (result) { persons = result}); alert(persons);` The alert shows the persons is null. If I put the alert inside the anonymous function, I get the data back. So there's no way to assign the result to a variable and use it outside of the function? It looks like whatever I want to do with the result should happen in the callback function only. I think I'm going back to my original question. – tempid Feb 18 '12 at 00:49
  • You can't use persons before you actually get the value from the server, and that is after the callback starts executing. You are using persons directly after you make the call. At this point of time you don't have the data yet. If you put alert(persons) in the callback it works (as long as the server is sending what you expect). – User Feb 18 '12 at 00:59
  • Ok "callback starts executing" is not correct - I mean after you initialize persons in the callback. After that you can use it. – User Feb 18 '12 at 01:07
  • So, simply put, I can only access `persons` within that callback function. Can I call another function within that callback so at that point the persons object is filled? – tempid Feb 18 '12 at 01:12
  • Sure, you can pass it as a parameter to other function or do whatever you want with it. You can also access persons from a completly different place in your code, as long as the scope is correct and you know that the point of time is after the variable was set. – User Feb 18 '12 at 01:20
0

I know I've gotten [object][Object] back before....are you sure your application is returning json? If not, Json.NET makes it pretty easy. You might need to call $.parseJSON too.

0

$.ajax is a generic jQuery function.

You want to do something like this:

$(function() {
            function LoadPersons(data) {
                // do something with data
            }

            $.ajax({
                type: 'POST',
                url: url,
                data: JSON.stringify(parameters),
                contentType: 'application/json;',
                dataType: 'json',
                success: function(result) {
                    // do something with persons (data)
                    // e.g. LoadPersons(data);
                }
            });
   });

In text form:

Your ajax success should be the bit that's responsible for doing something with the data after it's successfully been returned. Your previous method tries to return data before the AJAX method has necessarily been completed. You can just add the $.ajax method directly inside $(function() { .. }) so it's called upon page load.

Also, I recommend using a tool such as Firebug to examine the output / response of AJAX calls.

  • 1
    Thank you. That is how I had it before. The page makes about 10 such ajax calls (different url's and params) and I just wanted to make it generic. Looks like it can't be done without using `async:false` but the drawback is it is locking up the browser. Oh well! – tempid Feb 18 '12 at 00:20