Search code examples
jqueryjquery-callbackloose-coupling

Loose coupling of custom callbacks in jQuery


I was wondering if there exists a design pattern/framework which allows for the loose coupling of callbacks in jQuery.

Basically, I have a ajax call which retrieves settings that will be required in the callback functions. I have a number of functions that I wish to fire after the ajax call is complete but would like to avoid doing something like:

$.getJSON('/webservice/config', function(data) {
    functionA();
    functionB();
}

I'd like it to be loosely coupled. Does anyone have an idea on how this is popssible?

Thanks, Gearoid.

SOLUTION

Here's what I used in the end:

function initConfig(callbacks) {

    $.getJSON('/webservices/config', function(data) {       

        $.each(data.config, function(key, value) { 
          config[data.config[key].paramName] = data.config[key].paramValue; 
        });

    }).done(function() {
        //callbacks
        callbacks.forEach(function(callback) {
           if (eval('typeof ' + callback) == 'function') {
            window[callback]();
        });
    });
}

My code is then quite loosely coupled as I can pass any number of callback functions to the original function and they will run sequentially, eg:

initConfig('setLocationData', 'setUserData');

Solution

  • The jqXHR object, which is the return value of all AJAX queries, supports a done method which allows you to bind arbitary functions which are executed on the completion of the request;

    jQuery.getJSON('/foo.json').done(function () {
     // One success handler
    }).done(function () {
     // Another success handler
    });
    

    This is because the AJAX module was rewritten in jQuery 1.5 to use the Deferred interface, which guarantees the execution of handlers which are bound either before or after the callback fires.

    Edit: Explain my comment

    function initConfig() {
        return $.getJSON('/webservices/config', function(data) {       
            $.each(data.config, function(key, value) { 
              config[data.config[key].paramName] = data.config[key].paramValue; 
            });
        });
    }
    
    initConfig().done(setLocationData, setUserData);