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.