jQuery Ajax How do callbacks work?

Hello fellow programmers! I just started an additional programming project and swore to god my code will bo SO much cleaner and easily upgradeable than it has been before.

Then I stumbled upon my "arch enemy" the jQuery AJAX returning. Last time I wanted to return something from an AJAX call I had to bend over and just make the call synchronous. That made things sticky and ugly and I hope that this time I will find something better.

So I have been googling/searching stackoverflow for a while now, and just don't understand this solution many ppl has gotten which is called callback function. Could someone give me an example on how I could exploit these callback functions in order to return my login statuses:

function doLogin(username, password) {
    $.ajax({
        url:        'jose.php?do=login&user='+username+'&pass='+password,
        dataType:   'json',
        success:    function(data) {
                        if(data.success==1) {
                            return('1');
                        } else {
                            return('2');
                        }
                        $('#spinner').hide();
                    },
        statusCode: {
                        403:function() {
                            LogStatus('Slavefile error: Forbidden. Aborting.');
                            $('#spinner').hide();
                            return (3);
                        },
                        404:function() {
                            LogStatus('Slavefile was not found. Aborting.');
                            $('#spinner').hide();
                            return (3);
                        },
                        500:function() {
                            LogStatus('Slavefile error: Internal server error. Aborting.');
                            $('#spinner').hide();
                            return (3);
                        },
                        501:function() {
                            LogStatus('Slavefile error: Not implemented. Aborting.');
                            $('#spinner').hide();
                            return (3);
                        }
                    },
        async:      true
    });
}

So as you probably know, you cannot use return the way I have done from inside an AJAX call. You should instead use callback functions which I have no idea of how to use.

I'd be VERY greatful if someone could write me this code using callback functions and explaining to me just HOW they WORK.

EDIT:

I REALLY need to return stuff, not use it right away. This function is being called from within another function and should be able to be called from different places without being rewritten even slightly.

/EDIT

Sincerly,

Akke

Web Developer at Oy Aimo Latvala Ab

Answers


There are three parts to the basic "I need an asynchronous callback" pattern:

  1. Give the function a callback function parameter.
  2. Call the callback function instead of returning a value.
  3. Instead of calling the function and doing something with its return value, the return value will be passed to your callback function as a parameter.

Suppose your synchronous mind wants to do this:

function doLogin(username, password) {
    // ...
    return something;
}

switch(doLogin(u, p)) {
case '1':
    //...
    break;
case '2':
    //...
    break;
//...
}

but doLogin has to make an asynchronous call to a remote server. You'd just need to rearrange things a little bit like this:

function doLogin(username, password, callback) {
    return $.ajax({
        // ...
        success: function(data) {
            if(data.success == 1)
                callback('1');
            else
                callback('2');
        },
        //...
    });
}

var jqxhr = doLogin(u, p, function(statusCode) {
    switch(statusCode)) {
    case '1':
        //...
        break;
    case '2':
        //...
        break;
    //...
    }
});

The jqxhr allows you to reference the AJAX connection before it returns, you'd use it if you needed to cancel the call, attach extra handlers, etc.


A callback is simply a function that runs when certain conditions are met. In this case, it is when ajax has a "success".

You are already using a callback, but you don't recognize it. success: function(data) {} is a callback, but it's just what's called an anonymous function. It has no name or reference, but it still runs. If you want to change this anonymous function to a named function, it is really simple: take the code in the anonymous function, and put it in a named one, and then just call the named one:

[...]success:    function(data) {
    if(data.success==1) {
        return('1');
    } else {
        return('2');
    }
    $('#spinner').hide();
}, [...]

should change to:

[...]success:    function(){ callbackThingy(data) }, [...]

And now just create the callbackThingy function:

function callbackThingy(data){
    if(data.success==1) {
        someOtherFunction('1');
    } else {
        someOtherFunction('2');
    }
    $('#spinner').hide();
}

Note that the "return" value does nothing. It just stops the callback function, whether you are in an anonymous function or a named one. So you would also have to write a second function called someOtherFunction:

function someOtherFunction(inValue){
    if(inValue=='1') {
        // do something.
    } else if(inValue=='2') {
        // do something else.
    }
}

The above example is if you have to pass parameters. If you do not need to pass parameters, the setup is simpler:

[...]success:  callbackThingy, [...]

function callbackThingy(){
    // do something here.
}

From the edit in your original post, I can see that you just need to store a (more) global variable. Try this:

// in the global scope , create this variable:
// (or -- at least -- in the scope available to both this ajax call 
// and where you are going to use it)
var valHolder = -1;

// then edit your ajax call like this:
[...] 
success:    function(data) {
    if(data.success==1) {
        valHolder = 1;
    } else {
        valHolder = 2;
    }
    $('#spinner').hide();
}, 
[...]

Now you can verify 3 things:

valHolder = -1 means that the ajax call has not yet returned successfully

valHolder = 1 means data.success = 1

valHolder = 2 means data.success != 1.

Another option is to store the variable in an HTML attribute of some element.

Finally, you should probably look at jquery.data for the most jquery way of managing stored data.

Does this help?


Just as a small point of interest, you don't have to include

async : true;

as part of your $.ajax options. The default setting for async is already "true".

Sorry to post this as a response, but until I have 50 rep I can't make a simple comment. (Feel free to help me out with that! ^_^ )


Need Your Help

Laravel 4 blade templates causing FatalErrorException?

laravel laravel-4

I'm getting an unexplained FatalErrorException when trying to implement a simple page layout using blade templating. I'm not sure if it's something I'm doing wrong or Laravel is. I'm following the

Is it possible to use WMI in a Windows service?

c# windows-services wmi

I'm writing a simple service to set the default printer based on where I'm connected, but I'm having trouble using WMI in my service. The more I think about it the less I think it's possible to do...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.