Loose coupling of custom callbacks in jQuery

331 Views Asked by At

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');
3

There are 3 best solutions below

4
On BEST ANSWER

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);
2
On

The $.ajax function can accept multiple success callbacks. Quote from http://api.jquery.com/jQuery.ajax/:

As of jQuery 1.5, the success setting can accept an array of functions. Each function will be called in turn.

Short example: (see http://jsfiddle.net/JhTDW/)

$.ajax({
  url: '/echo/json/',
  success: [
    function(data) {
      document.write('First callback: ' + data + '<br/>');
    },
    function(data) {
      document.write('Second callback: ' + data + '<br/>');
    }
  ]
});
1
On

Not sure how loosely it needs to be coupled, but in the success callback you could always send your data object to another function. But I'm not sure how this is going to decouple things. In one case, you're calling functionA() and functionB() from within the success callback; in the other case you're sending data over to utilityFunction() which is running functionA() and functionB().

In either case, you could have one or more conditionals in place to run functionA() or functionB() (or whatever other functions). But again, this could be done either in the success callback or in the utility function, so I'm still not sure where the decoupling will happen.

At the core of the question is this: You get data back, and presumably you want to act on that data or at least run logic depending on the response. It's about as decoupled as it's going to get, and from there it's just a matter of how you want to structure it.