src/data/question-groups/full-stack/content/async-javascript.md
JavaScript handles asynchronous operations, like fetching data from an API or reading files, through different paradigms: callbacks, promises, and async/await. Each offers unique advantages and challenges. Here's a detailed look:
What it is:
A callback is a function passed as an argument to another function to be executed later, usually after an asynchronous task completes.
Example:
fs.readFile('file.txt', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content:', data.toString());
});
Challenges:
Callback Hell: As tasks become more complex, nesting callbacks leads to hard-to-read and maintainable code.
doTask1(() => {
doTask2(() => {
doTask3(() => {
console.log('All tasks done!');
});
});
});
What it is:
A promise represents a value that may be available now, in the future, or never usually coming as a result of an asynchronous operation. It provides a cleaner way to handle asynchronous operations, chaining actions with .then() and catching errors with .catch().
Example:
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => {
console.log('Fetched data:', data);
})
.catch((error) => {
console.error('Error fetching data:', error);
});
Advantages:
What it is:
Async/await is built on promises but provides a more synchronous and readable syntax for managing this type of code.
Functions declared with async automatically return a promise, and the await keyword pauses execution until a promise resolves.
Example:
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log('Fetched data:', data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
Advantages:
try/catch blocks.