Callbacks

Contact Us or call 1-877-932-8228
Callbacks

Callbacks

In JavaScript, callbacks are functions called by other functions which take the first function as a parameter. We can do this - pass a function to another function as an argument - because, in JavaScript, functions are objects. One of the key benefits of using callback functions is using them asynchonously: we want them to work, usually, in response to some event - but only when that event fires.

You are likely familiar with callback functions from event handling in JavaScript:

var myButton = document.getElementById("myButton");
myButton.addEventListener("click", someRandomFunction);

In the example above, we attach an event listener to the button with id myButton, listening for clicks on that button. When a click happens - every time a click happens - we invoke the someRandomFunction function. It's not that we invoke/call function someRandomFunction when the click happens, but rather that we line up function someRandomFunction to be called ("called back") upon the event of a click.

Another benefit to using callbacks is flexibility: in passing a function as a parameter to another function, we can slot in different functionality per our needs. Here's an example:

Code Sample:

AdvancedFunctions/Demos/callbacksOperations.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Callbacks - Operations</title>
	<style>
		input {
			padding:4px;
			width:57px;
		}
		input, button {
			padding:2px 5px;
			font-size:20px;
		}
	</style>
	<script>
		function doOperation(x, y, callbackFunction) {
			return callbackFunction(x, y);
		}
		function doAdd(x, y) {
			return x + y;
		}
		function doSubtract(x, y) {
			return x - y;
		}
		function doMultiply(x, y) {
			return x * y;
		}
		function doDivide(x, y) {
			return x / y;
		}

		function updateResult(e) {
			var targetID = e.target.id;
			var num1 = parseFloat(document.getElementById('num1').value);
			var num2 = parseFloat(document.getElementById('num2').value);
			var result = document.getElementById('result');
			switch (targetID) {
				case 'doAdd':
					var doOp = doAdd;
					break;
				case 'doSubtract':
					var doOp = doSubtract;
					break;
				case 'doMultiply':
					var doOp = doMultiply;
					break;
				case 'doDivide':
					var doOp = doDivide;
					break;
			}
			result.value = doOperation(num1, num2, doOp);
		}

		window.onload = function() {
			
			var buttons = document.getElementsByTagName('button');

			for (var i=0; i<buttons.length; i++ ) {
				buttons[i].addEventListener('click', function(e) {
					updateResult(e);
				}, 'false');
			}
		}
		
	</script>
</head>
<body>
	<h1>Callbacks - Operations</h1>
	<input type="text" id="num1">
	<input type="text" id="num2">
	<button id="doAdd" class="op">+</button>
	<button id="doSubtract" class="op">-</button>
	<button id="doMultiply" class="op">*</button>
	<button id="doDivide" class="op">/</button>
	<input type="text" id="result">
</body>
</html>

Code Explanation

The HTML markup for the page includes textfields for two numbers, four buttons (for operations "add", "subtract", "multiply", and "divide"), and a textfield for the result of performing the operation on the two user-entered numbers.

On the event of window.load, we attach an event listener to each button, calling function updateResult and passing to it the parameter e, the event object that contains details about the event that was triggered.

Function updateResult gets the value of the two numbers (converting them to integers) and, based on the id of the element that generated the event (doAdd, doSubtract, doMultiply, or doDivide, uses a switch statement to set a local variable, doOp as appropriate. We then set DOM element result's valuebased on function doOperation with the approprite callback function.

Note that we use parseFloat to convert the field values from a string to a floating-point number, so that we can use numeric values in our operations.

Function doOperation returns callbackFunction(x, y), where callbackFunction is the function passed in when doOperation is called.

Using callback functions in this manner gives us great flexibility:

  • Our "operation" functions (doAdd, doSubtract, etc.) can be tailored to just focus on the operations - a programming principle known as "Separation of Concerns".
  • We might do some validation inside doOperation to check to make sure we have the right values for our numbers ("divisor can't be zero" etc.).
  • A pattern like the one we have here would make it easy to import a library, say from a third-party developer, and easily add more-complex mathematical opertions easily to our existing page.
Next