DEV Community

Cover image for Callback functions in Javascript explained
Santiago Rincón
Santiago Rincón

Posted on

Callback functions in Javascript explained

Imagine you are leading a development team responsible for creating a website, and you've found that the only remaining task for your team is to add a logo to the website.

However, as a team of developers, you guys lack the necessary skills to design a professional logo. Thus, you must reach out to the design team to get the piece of art. Once the design team has provided the logo, you can then assign the task of adding it to the website to one of your developers.

It's currently 2 PM on a Friday and you're eagerly waiting for the design team to provide the necessary design. Nonetheless, as time passes, you become increasingly frustrated with the delay. Finally, at 4:30 PM, the design team delivers the art, and now you're able to assign the task to a developer. However, due to the delay, it is now 6 PM, and the team is frustrated that they could not complete the work earlier.

Now imagine instead of waiting for the design team to deliver before assigning the task to a developer, you could have asked the design team to provide the logo directly to the developer responsible for adding it to the website. That could have saved you time.

This way, the developer could have started working on the container and had everything ready to add the design as soon as it was received. Everyone's happy. This is a callback function, and it's such a magical thing.

So what exactly are callback functions?

In simple terms, a callback function is just a function you can pass to another function for it to be invoked after performing another action.

The most interesting thing about them is that we use them all the time without even realizing it. Here are some examples:

Event handling

In web development, callback functions are commonly used to handle events: mouse clicks, key presses, form submissions, and so on. Event listeners are attached to HTML elements and triggered when the corresponding event occurs. The callback function is then executed, allowing the program to respond to the event.

I'm sure you've used something like this.

const button = document.querySelector("button");

button.addEventListener("click", function() {
  console.log("Button clicked!");
});
Enter fullscreen mode Exit fullscreen mode

Asynchronous operations

Callback functions are often used in JavaScript to handle asynchronous operations, for example: making an HTTP request. The callback function is passed to the asynchronous function, and it is called when the data is fetched.

fetch("https://pokeapi.co/api/v2/pokemon/ditto")
  .then(function(response) {
    // callback function executed when the HTTP request is complete
    return response.json();
  })
  .then(function(data) {
    // callback function executed when the response is converted to JSON
    console.log(data);
  });
Enter fullscreen mode Exit fullscreen mode

Array iteration

The Array.prototype.forEach(), Array.prototype.map(), etc. methods are examples of built-in JavaScript functions that take a callback function as an argument. These functions are used to iterate through an array and perform some operation for each element.

const numbers = [1, 2, 3, 4, 5];

// forEach method with callback function
numbers.forEach(function(number) {
  console.log(number);
});

// map method with callback function
const squaredNumbers = numbers.map(function(number) {
  return number * number;
});
Enter fullscreen mode Exit fullscreen mode

In all of these examples, callback functions allow programs to be more flexible and responsive to changing conditions. They allow us to write code that can respond to events or data as they become available, and provide a way to separate concerns in our code, making it more modular, scalable, and easier to maintain.

The best part of it is that you can implement them yourself. Let's take Array.prototype.map() to see calback functions in detail. This method takes a callback function as an argument and returns a new array with the result of calling the callback function on each element of the original array.

const numbers = [1, 2, 3, 4, 5];

const squaredNumbers = numbers.map(function(number) {
  return number * number;
});

console.log(squaredNumbers); // Output: [1, 4, 9, 16, 25]
Enter fullscreen mode Exit fullscreen mode

In this example, we have an array of numbers, and we want to create a new array with the squared values of each number. We can achieve this by calling the map() method on the numbers array and passing a callback function that takes a single argument (the current element of the array) and returns the squared value of that element.

The map() method then iterates through each element of the original array and applies the callback function to each element. The result of each call to the callback function is stored in a new array, which is returned once the iteration is done.

But, how does it work internally? Let's see a simplified example of how the map() method works.

Array.prototype.map = function(callback) {
  const newArray = []; // create a new array to store the result
  for (let i = 0; i < this.length; i++) { // iterate over each element of the original array
    const result = callback(this[i], i, this); // call the callback function on each element
    newArray.push(result); // add the result to the new array
  }
  return newArray; // return the new array with the results
};
Enter fullscreen mode Exit fullscreen mode

In this implementation, we define the map() method on the Array.prototype object, which allows us to call the method on any array object. The callback parameter is the function that will be called on each element of the array.

Inside the method, we create an empty array newArray to store the results of calling the callback function on each element. We then use a for loop to iterate over each element of the original array.

On each iteration, we call the callback function with three arguments: the current element of the array this[i], the index of the current element i, and the original array this. The callback function can use these arguments to transform the current element of the array and then return the transformed value.

We then add the result of the callback function to the newArray using the push() method, and finally, we return the newArray with the results of calling the callback function on each element of the original array.

Now let's try to turn the metaphor at the beginning of this post into code with and without callback functions.

With callback function

// Example with callback functions for website development process

// Assume we have a function that represents the development team
function developmentTeam() {
  console.log("Development team is ready to add the illustration to the website");
}

// Assume we have a function that represents the design team
function designTeam(callback) {
  console.log("Design team is working on the illustration...");
  setTimeout(function() {
    console.log("Design team finished the illustration!");
    callback();
  }, 1500); // Simulate a delay of 1.5 seconds to complete the illustration
}

// Assume we have a function that represents the implementation task
function implementationTask() {
  console.log("Developer added the illustration to the website");
}

// Assume we want to coordinate between the development and design teams to complete the website
developmentTeam();
designTeam(implementationTask);
Enter fullscreen mode Exit fullscreen mode

In this example, we have three functions: developmentTeam(), designTeam(callback), and implementationTask(). The first function represents the development team, while the second function represents the design team. The designTeam(callback) function takes a callback function as an argument, which represents the implementation task that the development team needs to perform.

Inside the designTeam(callback) function, we simulate a delay of 1.5 seconds to represent the time it takes for the design team to complete the design.

Once the design is completed, we call the callback function to notify the development team that they can proceed with the implementation task. Finally, we call developmentTeam() to indicate that the development team is ready to add the illustration to the website.

By using a callback function, we can ensure that the implementation task is only executed once the design team has completed the illustration. This helps to streamline the development process and avoid frustration on the development team.

Now without callback function

// Example without callback functions for website development process

// Assume we have a function that represents the development team
function developmentTeam() {
  console.log("Development team is ready to add the illustration to the website");
}

// Assume we have a function that represents the design team
function designTeam() {
  console.log("Design team is working on the illustration...");
  setTimeout(function() {
    console.log("Design team finished the illustration!");
    implementationTask();
  }, 1500); // Simulate a delay of 1.5 seconds to complete the illustration
}

// Assume we have a function that represents the implementation task
function implementationTask() {
  console.log("Developer added the illustration to the website");
}

// Assume we want to coordinate between the development and design teams to complete the website
developmentTeam();
designTeam();
Enter fullscreen mode Exit fullscreen mode

In this example, we have the same three functions: developmentTeam(), designTeam(), and implementationTask(). However, instead of passing a callback function to designTeam(), we call implementationTask() directly from within designTeam() once the deign is complete.

While this approach may work in some cases, it can lead to problems if the implementation task depends on other tasks that need to be completed before it. In such cases, it may be more difficult to manage the dependencies and ensure that tasks are executed in the correct order.

In general, using callback functions can help you simplify the development process and make it easier to manage complex dependencies between functions.

In conclusion, callback functions are an essential feature in JavaScript that allows developers to write asynchronous, event-driven code, among other things. By passing a function as an argument to another function, the callback function can be executed once the first function has completed its task. This allows us, developers, to write more efficient and maintainable code, as they can avoid blocking the execution of code while waiting for long-running operations to complete.

Callback functions are used extensively for many purposes, like handling user input, making HTTP requests, and working with timers. They are also commonly used in modern web development frameworks, such as Express and React, to handle asynchronous operations.

While callback functions can be a powerful tool in a developer's toolbox, it's essential to use them carefully and understand the potential pitfalls. For example, callback functions can lead to callback hell, where the code becomes difficult to read and manage due to excessive nested callbacks. Developers should also consider using other techniques, such as promises or async/await, to manage complex dependencies between functions.

Overall, callback functions are a crucial part of JavaScript, and every developer should understand how to use them effectively to write efficient, scalable, and maintainable code.

Top comments (0)

More from Santiago Rincón

Recursion in Javascript Why to keep it simple How to add a custom font to an HTML canvas

玻璃钢生产厂家深圳商业商场美陈费用精细玻璃钢座椅雕塑昆山玻璃钢仿真植物水果雕塑玻璃钢动物雕塑 临朐曲阳玻璃钢浮雕雕塑国源玻璃钢雕塑广西玻璃钢金属雕塑厂家浙江商场美陈厂家直销商场美陈软装视频丽水玻璃钢雕塑批发四川特色商场美陈湘潭玻璃钢十二生肖雕塑商场情人节美陈方案宁夏广场玻璃钢雕塑公司濮阳大型玻璃钢景观雕塑伊犁玻璃钢雕塑厂玻璃钢卡通雕塑厂家联系方式绍兴玻璃钢人物雕塑厂家供应湖北海洋生物玻璃钢雕塑价格二手玻璃钢雕塑卡通怀化玻璃钢花盆花器常州广场玻璃钢花盆烟台玻璃钢卡通雕塑价格玻璃钢雕塑武汉玻璃钢雕塑怎么制作的安徽佛像玻璃钢雕塑多少钱公园摆件玻璃钢雕塑销售价格广东玻璃钢卡通雕塑熊出没福州模压法玻璃钢雕塑定制武汉镂空玻璃钢仿铜雕塑厂家香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化