# How to Use Async and Await in JavaScript

[JavaScript's](https://bytescrum.com/) `async` and `await` keywords, introduced in ECMAScript 2017, revolutionized how developers handle asynchronous operations. They provide a more readable and convenient way to work with Promises, making asynchronous code appear more like synchronous code.

### What are `async` and `await`?

* `async`: The `async` keyword is used to declare an asynchronous function. An asynchronous function returns a Promise, implicitly making it a Promise-returning function.
    
* `await`: The `await` keyword can only be used inside an `async` function. It pauses the execution of the `async` function, waiting for the Promise to resolve or reject. Once resolved, it returns the result. If the Promise is rejected, it throws an error, which can be caught using `try...catch`.
    

### Basic Usage

Here's a simple example to illustrate the use of `async` and `await`:

```javascript
// Simulate an asynchronous operation with a Promise
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 2000);
  });
}

// Declare an async function
async function getData() {
  try {
    // Use await to wait for the Promise to resolve
    const data = await fetchData();
    console.log(data); // Output: Data fetched successfully
  } catch (error) {
    console.error('Error:', error);
  }
}

// Call the async function
getData();
```

In this example:

* The `fetchData` function simulates an asynchronous operation using a Promise that resolves after 2 seconds.
    
* The `getData` function is declared as `async`, allowing the use of `await` inside it to pause execution until `fetchData` resolves.
    
* If `fetchData` throws an error, it will be caught by the `catch` block in `getData`.
    

### Handling Multiple Promises

When dealing with multiple asynchronous operations, `async` and `await` can make the code much cleaner and easier to follow compared to chaining `.then()` and `.catch()`.

```javascript
function fetchUser() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: 1, name: 'John Doe' });
    }, 1000);
  });
}

function fetchPosts(userId) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(['Post 1', 'Post 2', 'Post 3']);
    }, 1000);
  });
}

async function getUserData() {
  try {
    const user = await fetchUser();
    const posts = await fetchPosts(user.id);
    console.log('User:', user);
    console.log('Posts:', posts);
  } catch (error) {
    console.error('Error:', error);
  }
}

getUserData();
```

In this example:

* `fetchUser` and `fetchPosts` are asynchronous functions that return [Promises](https://blog.bytescrum.com/understanding-promises-in-nodejs-a-comprehensive-guide).
    
* The `getUserData` function uses `await` to wait for both Promises to resolve sequentially, making the code easy to read and understand.
    

### Parallel Execution with `Promise.all`

Sometimes, you want to run asynchronous operations in parallel to improve performance. You can achieve this with `Promise.all` combined with `async` and `await`.

```javascript
function fetchData1() {
  return new Promise(resolve => setTimeout(() => resolve('Data 1'), 1000));
}

function fetchData2() {
  return new Promise(resolve => setTimeout(() => resolve('Data 2'), 1000));
}

async function getAllData() {
  try {
    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
    console.log('Data 1:', data1);
    console.log('Data 2:', data2);
  } catch (error) {
    console.error('Error:', error);
  }
}

getAllData();
```

In this example:

* `fetchData1` and `fetchData2` are called concurrently.
    
* `Promise.all` waits for all Promises to resolve and returns an array of results, which is then destructured into `data1` and `data2`.
    

### Error Handling

Error handling in `async`/`await` is straightforward with `try...catch`.

```javascript
function fetchDataWithError() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error('Something went wrong'));
    }, 1000);
  });
}

async function getDataWithErrorHandling() {
  try {
    const data = await fetchDataWithError();
    console.log('Data:', data);
  } catch (error) {
    console.error('Caught an error:', error);
  }
}

getDataWithErrorHandling();
```

In this example:

* If `fetchDataWithError` rejects, the error is caught in the `catch` block, and the error message is logged.
    

<details data-node-type="hn-details-summary"><summary>Conclusion</summary><div data-type="detailsContent">The <code>async</code> and <code>await</code> keywords provide a powerful and elegant way to handle asynchronous operations in JavaScript. They simplify the code, making it more readable and maintainable, especially when dealing with complex sequences of asynchronous operations. By using <code>async</code> and <code>await</code>, developers can write asynchronous code that looks and behaves like synchronous code, reducing the cognitive load and potential for errors.</div></details>
