Blog#174: 🤔Understanding Asynchronous JavaScript: 🔄Callbacks, 🤞Promises, and 🤝Async/Await

174

Hi, I'm Tuan, a Full-stack Web Developer from Tokyo 😊. Follow my blog to not miss out on useful and interesting articles in the future.

1. Introduction to Asynchronous JavaScript

What is Asynchronous JavaScript?

In plain English, asynchronous JavaScript means that some tasks can be executed without blocking or waiting for other tasks to finish. This allows for a more efficient use of time, as your program can continue to do other things while waiting for a task to complete.

Why is Asynchronous Programming Important?

Imagine going to a fast-food restaurant. You place your order, and then you have to wait for the staff to prepare it. In the meantime, the cashier can serve other customers, instead of making everyone wait in a long line. Asynchronous programming in JavaScript works in a similar way, allowing your code to run smoothly without being blocked by time-consuming tasks.

2. Callbacks

What are Callbacks?

A callback is simply a function that is passed as an argument to another function and is executed at a later point in time. Callbacks are a way to handle asynchronous tasks in JavaScript.

How Do Callbacks Work?

Let's use an example to understand how callbacks work. Imagine you want to make a request to a server to get some data. This request may take some time to complete, and you don't want your entire application to wait for it. You can use a callback function to handle this.

function getDataFromServer(url, callback) {
  // Simulate a request to the server
  setTimeout(() => {
    console.log('Data received from the server');
    callback();
  }, 2000);
}

function processData() {
  console.log('Processing the data');
}

getDataFromServer('https://example.com/data', processData);

In this example, getDataFromServer takes a URL and a callback function as arguments. The setTimeout function simulates the delay that may occur while making a request to the server. After 2 seconds, the console.logstatement is executed, and then the callback function processData is called.

The Problem with Callbacks

The main issue with callbacks is the so-called "callback hell," which is when multiple callbacks are nested within one another. This can lead to messy, hard-to-read code.

3. Promises

What are Promises?

Promises are a more advanced way to handle asynchronous tasks in JavaScript. A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

How Do Promises Work?

A Promise is created using the Promise constructor, which takes a single argument: a function called the "executor." The executor function takes two arguments: a "resolve" function and a "reject" function.

  • The resolve function is used to fulfill the promise with a resulting value.
  • The reject function is used to reject the promise with a reason (usually an error).

Here's an example of creating a Promise:

const myPromise = new Promise((resolve, reject) => {
  // Do some asynchronous task
  setTimeout(() => {
    resolve('Success!');
  }, 2000);
});

myPromise.then(result => {
  console.log(result); // Success!
});

Chaining Promises

One of the key features of Promises is the ability to chain them together. This allows you to perform a series of asynchronous tasks in a more organized and readable way.

function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Data from ${url}`);
    }, 2000);
  });
}

fetchData('https://example.com/data1')
  .then(data1 => {
    console.log(data1); // Data from https://example.com/data1
    return fetchData('https://example.com/data2');
  })
  .then(data2 => {
    console.log(data2); // Data from https://example.com/data2
    return fetchData('https://example.com/data3');
  })
  .then(data3 => {
    console.log(data3); // Data from https://example.com/data3
  })
  .catch(error => {
    console.error('An error occurred:', error);
  });

In this example, we've created a fetchData function that returns a Promise. We then use the then method to chain the Promises together. If an error occurs, the catch method will handle it.

4. Async/Await

What is Async/Await?

Async/await is a more modern way to work with asynchronous tasks in JavaScript, built on top of Promises. It allows you to write asynchronous code that looks and behaves like synchronous code, making it easier to read and understand.

How Does Async/Await Work?

To use async/await, you need to declare a function as async. Inside an async function, you can use the await keyword to pause the execution of the function until a Promise is resolved.

Here's an example using the same fetchData function from the previous section:

async function getData() {
  try {
    const data1 = await fetchData('https://example.com/data1');
    console.log(data1); // Data from https://example.com/data1

    const data2 = await fetchData('https://example.com/data2');
    console.log(data2); // Data from https://example.com/data2

    const data3 = await fetchData('https://example.com/data3');
    console.log(data3); // Data from https://example.com/data3
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

getData();

In this example, we declare the getData function as async. Inside the function, we use the await keyword to wait for the Promises returned by fetchData to resolve. If an error occurs, we handle it inside the catch block.

Async/Await with Error Handling

To handle errors in async/await, you can use the try and catch statements. The try block contains the code that might throw an error, while the catch block handles the error.

5. Conclusion

In this article, we've learned about asynchronous JavaScript and how to work with asynchronous tasks using callbacks, Promises, and async/await. Each method has its own advantages and use cases:

  • Callbacks are the most basic way to handle asynchronous tasks but can lead to "callback hell" and messy code.
  • Promises provide a more structured and readable way to handle asynchronous tasks, allowing for chaining and better error handling.
  • Async/await, built on top of Promises, allows you to write asynchronous code that looks and behaves like synchronous code, improving readability and maintainability.

Understanding these concepts and knowing when to use each method will help you write more efficient and organized JavaScript code, allowing your applications to run smoothly without being blocked by time-consuming tasks.

And Finally

As always, I hope you enjoyed this article and learned something new. Thank you and see you in the next articles!

If you liked this article, please give me a like and subscribe to support me. Thank you. 😊

NGUYỄN ANH TUẤN

Xin chào, mình là Tuấn, một kỹ sư phần mềm đang làm việc tại Tokyo. Đây là blog cá nhân nơi mình chia sẻ kiến thức và kinh nghiệm trong quá trình phát triển bản thân. Hy vọng blog sẽ là nguồn cảm hứng và động lực cho các bạn. Hãy cùng mình học hỏi và trưởng thành mỗi ngày nhé!

Đăng nhận xét

Mới hơn Cũ hơn