In this article I will attempt to explain the purpose and benefits of using callback functions in JavaScript.
Introduction
Basic JavaScript functions look like this normally like this
function addMe(a, b){ return a+ b }
JavaScript variables normally look like this
var a = 2 var b = 3
Finally we would call the function to add the variables
var theTotal = addMe(a, b) //5
Seems simple enough
Setting a variable to a function
But we can also combine them into something like this
var totalThis = function(a, b){ return a+b } var theTotal = totalThis(1, 2) //3
The point of this simple demo is to illustrate that a variable can be “equal” to a function. So that means we can pass it around as a function.
Creating a callback function
Here is an example:
function addMe(a, b, callback){ var theTotal = a+b callback(theTotal) }
Which is called like this
var theTotal = addMe(1, 2, function(val){ alert(val) })
Which returns 3
Walking through that…
- We created theTotal variable and made it equal to a function call to addMe
- We called the addMe function passing 1, 2 and a function with a value as a parameter
- The addMe function received the variables and assigned the name of the incoming function – callback
- the incoming function now known as callback was passed a pointer “val” which means it can be called with a parameter later
- note there are no () after callback it is the function arguements
- The addMe function added theTotal of a+b
- the addMe function called the callback function passing a parameter of theTotal
- The resulting total was passed back to the addMe function and back to theTotal as 3
Making it optional
If you want to make the callback optional (so it does not have to be called) then all we need to do it test for its existence within the addMe function:
function addMe(a, b, callback){ var theTotal = a+b if (callback){ callback(theTotal) } }
Some examples of why this makes your JavaScript code better
It is used in external libraries but other JavaScript developers and you will come across it and need to understand it. For example in jQuery, binding an event has been set up to allow “what you want to do after” to be passed in as a callback function. That gives maximum flexibility to the developer wanting to use bind().
$('#foo').bind('click', function() { alert('User clicked on "foo."'); });
The most common use would be in AJAX. Being asynchronous the webpage code carries on as if nothing else mattered once the ajax called is made. To get around this, modern JavaScript libraries use callback functions to process the data once the AJAX request is complete. So rather than having more code written after the AJAX call, the code is part of the function call which instantiates the AJAX in the first place. In this example the callback function is in the .done() part of the code which is itself a callback.
$.ajax({ url: "test.html", context: document.body }).done(function() { $(this).addClass("done"); });
And in XPages?
Well if you view the source of your XPage you will see a huge section at the end of the page with a whole load of functions and then a whole load of code which looks like XSP.attatchPartial (for example). That is dojo adding your programmatic events to the webpage onClientLoad as a callback.
For example here is a function
function view__id1__id11__id12__id113__id118_clientSide_onclick(thisEvent) { disableWorkingOverlay = true; }
And here is the attachPartial which only names the function
XSP.attachPartial("view:_id1:_id11:_id12:_id113:_id118", "view:_id1:_id11:_id12:_id113:open", null, "onclick", view__id1__id11__id12__id113__id118_clientSide_onclick, 2, "view:_id1:_id11:_id12:_id113:myFilesPanel");
Generic Functions
What this really means is the ability to make more optimized (generic) code. If you have a process with 3 steps, you could hard code each step into 3 functions. Say for example
- getData
- processData
- displayData
Well getData seem pretty generic to me and I expect we can use that more than once. So we would make a getData function, to which we would pass either the processData functionality (or) we would pass the necessary function call to take the data and move it to the next processData function. In that way we can use multiple dataSources and control the processing of the data from once central code block rather than having many individual code block for each individual process all over the place.
In the following code example the createGrid function is called as the callback function within the getGridData function. This makes the getGridData function completely generic and reusable. Get me some data and then do this with it.
var url = 'xRestService.xsp/byFirstNameFlat?count=100000', theData var theCallBack = function(theData){ createGrid(theData) } getGridData(url, theCallBack) //getGridData called from the code above function getGridData(url, callback){ $.ajax({ url: url }).done(function ( data ) { //one the data is loaded then pass it to the callback function //passed in as one of the function arguments if(callback){ callback(data) } }); } //createGrid - called from the callback function within getGridData function createGrid(data){ etc etc }
Conclusion
You are going to see callback functions all over the place when you start to look into adding external libraries to your XPages. Don’t be afraid of them. Consider them when creating your XPages functionality – even if it is as an unused options within a function, you never know when you might be glad of that later in the application development.
Reblogged this on Sutoprise Avenue, A SutoCom Source.
Cool!!!
What a great lesson…thanks!
Good explanation of callbacks.
Honestly, this is the clearest explanation of callbacks I’ve read. Thanks.
Thanks Mike and everyone else – always appreciate the feedback 🙂
Dr. Roden,
I am not so sure that your examples promote maintainability, as you are not really encapsulating your ‘reusable’ getGridData into anything besides the global namespace. In other words, if I create a function named getGridData in another xPage file or separate JS file and it gets added to the global namespace (via a script tag in the markup), then I will have two versions of the getGridData.
In my opinion, introducing namespaces into the JavaScript code would be more inline with the topic of maintainability, like this:
var utilities = utilities || {};
utilities.getGridData = function(url, callback) {
// Do your AJAX call here…
};
The above will look for an object an already declared object named utilities. If it finds that object, then it will append the getGridData to that existing object; otherwise a new object will be created (via {}) and then the getGridData function will be appended to the namespace.
Just to clarify, the .done() function is a jQuery wrapped set method that is syntactic sugar for a callback; it is not part of the JavaScript language as you are mildly implying.
Maybe a better title for your blog entry might be “How to make xPages work with JavaScript callbacks”
Karl
P.S. – Those auto-generated Dojo callbacks are nasty looking, I thought the ASP.NET master page nested controls name mangling was bad, but wow that is awful to look at. BTW, this is the Karl you used to work with at PDS.
Karl – thanks for reading the blog mate. I agree that saving the namespace is a better idea but that was not the focus of this article. Nice idea for a new one though – thanks 🙂
Hi Marky. Another great post. I use callbacks almost all the time. It takes a little getting used to in the beginning, but can easily become a great habit when coding in JavaScript.
Cheers man.