📖 JavaScript Callbacks
A callback is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of action.
Asynchronous Callbacks
Asynchronous callbacks are used to continue code execution after an asynchronous operation has completed. This is crucial for operations like event handling, timers, and API calls.
What is an API?
An API (Application Programming Interface) is a set of rules that allows different software entities to communicate with each other. In web development, APIs often refer to web services that provide data or functionality that can be accessed over the internet.
Example: setTimeout
function greet() {
console.log('Hello, world!');
}
setTimeout(greet, 2000); // 'Hello, world!' will be logged after 2 seconds
In this example, the greet
function is passed as a callback to the setTimeout
function. It will be executed after 2 seconds, making it a callback function.
Example: Event Listener
document.getElementById('btn').addEventListener('click', function() {
console.log('Button was clicked!');
});
In this example, an anonymous function is passed as a callback to the addEventListener
method. It will be executed whenever the specified event (click) occurs on the element, making it a callback function.
Position of Callback Functions
The position of the callback function in the argument list depends on the specific function or method:
setTimeout
: The callback is the first argument, followed by the delay in milliseconds.addEventListener
: The event type is the first argument, and the callback function is the second argument.
Example: API Call with Callbacks
Here's an example of how an API call can be made using callbacks. In this example, we simulate an API call with a timeout function.
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}`);
}
fetchData(displayData); // 'Name: John, Age: 30' will be logged after 2 seconds
In this example:
- The
fetchData
function simulates an API call by usingsetTimeout
to delay the execution of its inner code. - Inside
setTimeout
, after 2 seconds, an objectdata
is created with some dummy information. - The
callback
function, which is passed as an argument tofetchData
, is called withdata
as its argument. - The
displayData
function is defined to log the data to the console. - When
fetchData
is called withdisplayData
as its argument, after 2 seconds,displayData
is invoked with the dummy data, and it logs'Name: John, Age: 30'
to the console.
Putting It Into Action
To see these examples in action, create an HTML file and include the following script. This script will demonstrate the core principles of asynchronous callbacks and log the results to the console.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Asynchronous Callbacks Example</title>
</head>
<body>
<button id="btn">Click Me>/button>
<script>
// Example: setTimeout
function greet() {
console.log('Hello, world!');
}
setTimeout(greet, 2000); // 'Hello, world!' will be logged after 2 seconds
// Example: Event Listener
document.getElementById('btn').addEventListener('click', function() {
console.log('Button was clicked!');
});
// Example: API Call with Callbacks
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}`);
}
fetchData(displayData); // 'Name: John, Age: 30' will be logged after 2 seconds
</script>
</body>
</html>
Challenge
This challenge builds on the "Putting It Into Action" example. Modify the API call example to simulate a failure. Use a second callback to handle errors and log an error message to the console.
In order to check your learning, you should attempt to create a solution before revealing the provided solution below.
function fetchData(successCallback, errorCallback) {
setTimeout(() => {
const success = Math.random() > 0.5; // Randomly succeed or fail
if (success) {
const data = { name: 'John', age: 30 };
successCallback(data);
} else {
errorCallback('Failed to fetch data.');
}
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}`);
}
function handleError(error) {
console.error(error);
}
fetchData(displayData, handleError); // Will randomly log success or error after 2 seconds
Issues with Callbacks
Using callbacks for asynchronous operations can lead to complex and hard-to-read code, known as "callback hell". To address these issues, JavaScript introduced promises and async/await.
In the next sections, we will explore promises and async/await, which provide more elegant solutions for handling asynchronous code.