Understanding Asynchronous JavaScript: Callbacks, Promises, and Async/Await

2 mins read
7 Likes
178 Views

JavaScript is a single-threaded language, meaning it can only execute one task at a time. However, to handle tasks like API requests or database queries efficiently, it uses asynchronous programming. This allows other code to run while waiting for long operations to complete.


Let's explore the three core methods for handling asynchronous behavior: callbacks, promises, and async/await.


1. Callbacks

A callback is a function passed as an argument to another function, which is executed once the task is complete. This was the traditional way of handling asynchronous tasks in JavaScript.

Example:


function fetchData(callback) {
setTimeout(() => {
callback('Data received');
}, 2000);
}

fetchData((data) => {
console.log(data); // 'Data received' after 2 seconds
});


Drawback: Callbacks can lead to "callback hell," where multiple nested callbacks make code difficult to read and maintain.


2. Promises

To solve the callback hell problem, promises were introduced in ES6. A promise represents a value that may be available now, in the future, or never. It has three states:

  • Pending: Initial state, neither fulfilled nor rejected.
  • Fulfilled: Operation completed successfully.
  • Rejected: Operation failed.

Example:


const fetchData = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data received');
}, 2000);
});

fetchData
.then((data) => console.log(data)) // 'Data received'
.catch((error) => console.error(error));

Promises are more readable than callbacks but can still get complex when chaining.

3. Async/Await

Async/await syntax, introduced in ES8, simplifies the process of working with promises by allowing you to write asynchronous code in a synchronous manner.

  • async functions always return a promise.
  • await pauses the execution of the function until the promise resolves.

Example:


async function fetchData() {
try {
const data = await new Promise((resolve) => {
setTimeout(() => {
resolve('Data received');
}, 2000);
});
console.log(data); // 'Data received'
} catch (error) {
console.error(error);
}
}

fetchData();

Advantages of async/await:

  • Improved readability and maintainability.
  • Easier to handle errors using try/catch.

When to Use Which?

  • Callbacks: Use when working with legacy code or simple asynchronous operations.
  • Promises: Use for handling more complex asynchronous operations without getting into callback hell.
  • Async/Await: Ideal for modern JavaScript applications where readability is important.
Share:

Comments

0

Join the conversation

Sign in to share your thoughts and connect with other readers

No comments yet

Be the first to share your thoughts!