Understanding Callback function
Malcolm Kee
Posted on January 18, 2022
There are two ways to look at callback function:
- callback function as a way to reuse code for different operations
- callback function as a way for async programming
In this article, we'll learn the first way to look at callback function.
Prerequisite: you need to understand while
loop to understand the example
Parameters to reuse code for different data
Let's recap the concept of using parameter to allow function to run code for different data.
Consider the following FizzBuzz code:
let i = 1;
while (i <= 100) {
if (i % 3 === 0 && i % 5 === 0) {
// log 'FizzBuzz' when the result is multiply of 3 and multiply of 5
console.log('FizzBuzz');
} else if (i % 3 === 0) {
// log 'Fiz' when the result is multiply of 3
console.log('Fizz');
} else if (i % 5 === 0) {
// log 'Buzz' when the result is multiply of 5
console.log('Buzz');
} else {
// log the number
console.log(i);
}
}
Assuming that we need to support additional two scenarios:
- Do the FizzBuzz for numbers from -50 to 50
- Do the FizzBuzz for numbers from 0 to 1000
To do so, instead of copy pasting our FizzBuzz code above, let's create a function:
function fizzBuzz() {
let i = 1;
while (i <= 100) {
if (i % 3 === 0 && i % 5 === 0) {
// log 'FizzBuzz' when the result is multiply of 3 and multiply of 5
console.log('FizzBuzz');
} else if (i % 3 === 0) {
// log 'Fiz' when the result is multiply of 3
console.log('Fizz');
} else if (i % 5 === 0) {
// log 'Buzz' when the result is multiply of 5
console.log('Buzz');
} else {
// log the number
console.log(i);
}
}
}
fizzBuzz();
The code will still works as before. However, now that we put the code into a function, we can "parameterize" the data (start number (1
) and end number (100
)) so that we can support different start/end numbers:
function fizzBuzz(start, end) {
let i = start;
while (i <= end) {
if (i % 3 === 0 && i % 5 === 0) {
// log 'FizzBuzz' when the result is multiply of 3 and multiply of 5
console.log('FizzBuzz');
} else if (i % 3 === 0) {
// log 'Fiz' when the result is multiply of 3
console.log('Fizz');
} else if (i % 5 === 0) {
// log 'Buzz' when the result is multiply of 5
console.log('Buzz');
} else {
// log the number
console.log(i);
}
}
}
fizzBuzz(1, 100);
Now that fizzBuzz
is a function that can be used to support the additional two scenarios:
-
Do the FizzBuzz for numbers from -50 to 50
fizzBuzz(-50, 50);
-
Do the FizzBuzz for numbers from 0 to 1000
fizzBuzz(0, 1000);
Parameters to reuse code for different operations
Let's take one step further, how can we abstract away the console.log
calls?
Assuming that we need to run similar logic like FizzBuzz, but this time, we need to show the FizzBuzz/Fiz/Buzz messages in two other ways:
-
alert
the message - append the message into a
div
with idmessage
What we'll do, is similar to what we did with "parameterize" data in previous section, it is just that we will "parameterize" the statement instead.
Let's see:
function fizzBuzz(start, end, showFizzBuzz, showFizz, showBuzz) {
let i = start;
while (i <= end) {
if (i % 3 === 0 && i % 5 === 0) {
// log 'FizzBuzz' when the result is multiply of 3 and multiply of 5
// console.log('FizzBuzz');
showFizzBuzz();
} else if (i % 3 === 0) {
// log 'Fiz' when the result is multiply of 3
// console.log('Fizz');
showFizz();
} else if (i % 5 === 0) {
// log 'Buzz' when the result is multiply of 5
// console.log('Buzz');
showBuzz();
} else {
// log the number
console.log(i);
}
}
}
fizzBuzz(
1,
100,
function() {
console.log('FizzBuzz');
},
function() {
console.log('Fizz');
},
function() {
console.log('Buzz');
}
);
What we did:
- Comment out the previous
console.log
and replace it with calling the 3 new parametersshowFizzBuzz
,showFizz
, andshowBuzz
. - pass additional 3 arguments (each of them a function) for the 3 new parameters we introduce.
The reason that we can "parameterize" statement is that we can pass function as parameter in JavaScript.
Now we can support the additional two scenarios:
-
alert
the message
fizzBuzz( 1, 100, function() { alert('FizzBuzz'); }, function() { alert('Fizz'); }, function() { alert('Buzz'); } );
-
append the message into a
div
with idmessage
fizzBuzz( 1, 100, function() { const target = document.querySelector('#message'); target.append('FizzBuzz'); }, function() { const target = document.querySelector('#message'); target.append('Fizz'); }, function() { const target = document.querySelector('#message'); target.append('Buzz'); } );
Passing Parameter to Callback Function
With the current code, you may realize that we need to pass 3 functions to fizzBuzz
, and they are almost similar except the message is different.
We can simplify it by realizing the fact that callback function can accept parameters. Let's see how to simplify the fizzBuzz
code:
function fizzBuzz(start, end, showMessage) {
let i = start;
while (i <= end) {
if (i % 3 === 0 && i % 5 === 0) {
// log 'FizzBuzz' when the result is multiply of 3 and multiply of 5
// console.log('FizzBuzz');
// showFizzBuzz();
showMessage('FizzBuzz');
} else if (i % 3 === 0) {
// log 'Fiz' when the result is multiply of 3
// console.log('Fizz');
// showFizz();
showMessage('Fizz');
} else if (i % 5 === 0) {
// log 'Buzz' when the result is multiply of 5
// console.log('Buzz');
// showBuzz();
showMessage('Buzz');
} else {
// log the number
console.log(i);
}
}
}
fizzBuzz(
1,
100,
function(msg) {
console.log(msg);
}
);
What we did:
- Replace the 3 parameters
showFizzBuzz
,showFizz
, andshowBuzz
with a single genericshowMessage
parameter. - Call
showMessage
with the message as parameter. - replace the previous 3 function arguments with a single function that will accept
msg
as parameter.
The updated 2 more scenarios:
-
alert
the message
fizzBuzz( 1, 100, function(msg) { alert(msg); } );
-
append the message into a
div
with idmessage
fizzBuzz( 1, 100, function(msg) { const target = document.querySelector('#message'); target.append(msg); } );
Posted on January 18, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.