Understanding Callback function
Tags: javascript, fundamentals, callback
Published: 2022-01-18 08:28:53

---
title: Understanding Callback function
published: true
description: 
tags: javascript, fundamentals, callback
//cover_image: https://direct_url_to_image.jpg
---

There are two ways to look at callback function:

1. callback function as a way to reuse code for different operations
2. callback function as a way for async programming

In this article, we'll learn the first way to look at callback function.

---

<aside>

Prerequisite: you need to understand `while` loop to understand the example

</aside>

---

## 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:

```js
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:

1. Do the FizzBuzz for numbers from -50 to 50
2. 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:

```js
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:

```js
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:

1. Do the FizzBuzz for numbers from -50 to 50
    
    ```js
    fizzBuzz(-50, 50);
    ```
    
2. Do the FizzBuzz for numbers from 0 to 1000
    
    ```js
    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:

1. `alert` the message
2. append the message into a `div` with id `message`

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:

```js
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:

1. Comment out the previous `console.log` and replace it with calling the 3 new parameters `showFizzBuzz`, `showFizz`, and `showBuzz`.
2. pass additional 3 arguments (each of them a function) for the 3 new parameters we introduce.

---

<aside>

The reason that we can "parameterize" statement is that we can pass function as parameter in JavaScript.

</aside>

---

Now we can support the additional two scenarios:

1. `alert` the message
    
    ```js
    fizzBuzz(
      1,
      100,
      function() {
        alert('FizzBuzz');
      },
      function() {
        alert('Fizz');
      },
      function() {
        alert('Buzz');
      }
    );
    ```
    
2. append the message into a `div` with id `message`
    
    ```js
    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:

```js
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:

1. Replace the 3 parameters `showFizzBuzz`, `showFizz`, and `showBuzz` with a single generic `showMessage` parameter.
2. Call `showMessage` with the message as parameter.
3. replace the previous 3 function arguments with a single function that will accept `msg` as parameter.

The updated 2 more scenarios:

1. `alert` the message
    
    ```js
    fizzBuzz(
      1,
      100,
      function(msg) {
        alert(msg);
      }
    );
    ```
    
2. append the message into a `div` with id `message`
    
    ```js
    fizzBuzz(
      1,
      100,
      function(msg) {
        const target = document.querySelector('#message');
        target.append(msg);
      }
    );
    ```