Async/await in JavaScript

Async/await in JavaScript

In this article, we will explain async/await in JavaScript.

YouTube Video

Async/await in JavaScript

async (and await) in JavaScript are features designed to make writing asynchronous operations more intuitive and readable. By using this, you can reduce the complexity of traditional callback functions and Promise chains, and write asynchronous code in a way that looks like synchronous code.

async Function

async is used to define a function as an asynchronous function. An async function always returns a Promise. Within a function marked with async, you can use await to wait for the result of a Promise to be returned.

Basic Syntax of an async Function

1async function myAsyncFunction() {
2    // Write asynchronous processing here
3    return 'Result';  // Return a Promise
4}

In this case, calling myAsyncFunction() automatically returns a Promise object. When the Promise is resolved, its result becomes the value returned by return.

Example: Basic async Function

1async function greet() {
2    return 'Hello, World!';
3}
4
5greet().then((message) => {
6    console.log(message);  // Displays "Hello, World!"
7});

await

await is used to wait for a Promise to be resolved. By using await, you can pause the execution until the Promise is resolved and receive the result of the Promise. await can only be used inside an async function.

Example: How to Use await

 1async function fetchData() {
 2    // Wait for the result of the Promise
 3    const data = await fetch('https://codesparklab.com/json/example.json');
 4    // Wait for the asynchronous operation to complete
 5    const jsonData = await data.json();
 6    // Retrieve and display the data
 7    console.log(jsonData);
 8}
 9
10fetchData();

In the example above, it waits for the Promise returned by the fetch function with await, and then performs further asynchronous operations using the result.

Error Handling with async/await

If an error occurs inside an async function, that error is treated as a reject of the Promise. You can use try...catch statements to perform error handling.

Example: Error Handling

 1async function fetchData() {
 2    try {
 3        // Invalid URL
 4        const data = await fetch('https://invalid.codesparklab.com/');
 5        const jsonData = await data.json();
 6        console.log(jsonData);
 7    } catch (error) {
 8        // Catch the error
 9        console.error('Failed to fetch data:', error);
10    }
11}
12
13fetchData();

Using a try...catch block allows you to catch errors that occur during asynchronous operations, preventing the program from crashing when errors occur.

Benefits of async/await

Compared to traditional Promise chains, async/await offers the following advantages:.

  • Improved readability
    • Asynchronous processing can be written like synchronous code, avoiding the complexity of deeply nested Promise chains and callbacks.
  • Easier debugging
    • Since it resembles synchronous code, debugging and error handling become easier.
  • Better maintainability
    • Asynchronous processes can be written more simply, making it easier to change or modify the code and improving long-term maintainability.

Example: Promise chain vs async/await

Let’s compare code using Promise chains and code using async/await.

 1// Code using Promise chains
 2function fetchDataPromise() {
 3    fetch('https://codesparklab.com/json/example.json')
 4        .then((response) => response.json())
 5        .then((data) => {
 6            console.log(data);
 7        })
 8    .catch((error) => {
 9        console.error('Failed to fetch data:', error);
10    });
11}
12
13// Code using async/await
14async function fetchDataAsync() {
15    try {
16        const response = await fetch('https://codesparklab.com/json/example.json');
17        const data = await response.json();
18        console.log(data);
19    } catch (error) {
20        console.error('Failed to fetch data:', error);
21    }
22}

As you can see, using async/await allows you to write asynchronous processes in a linear fashion, resulting in more readable code.

Execute multiple asynchronous operations simultaneously

By combining Promise.all() or Promise.race() with await, you can execute multiple asynchronous operations simultaneously and handle their results collectively.

Promise.all()

 1async function fetchMultipleData() {
 2    try {
 3        const [data1, data2] = await Promise.all([
 4            fetch('https://codesparklab.com/json/example1.json'),
 5            fetch('https://codesparklab.com/json/example2.json')
 6        ]);
 7        const jsonData1 = await data1.json();
 8        const jsonData2 = await data2.json();
 9        console.log(jsonData1);
10        console.log(jsonData2);
11    } catch (error) {
12        console.error('Failed to fetch data:', error);
13    }
14}
15
16fetchMultipleData();
  • Promise.all() resolves multiple Promises simultaneously and returns their results as an array. It waits for all Promises to be resolved, and if any of them fail, it is considered a failure overall.

Promise.race()

 1async function fetchFastestData() {
 2    try {
 3        const fastestResponse = await Promise.race([
 4            fetch('https://codesparklab.com/json/example1.json'),
 5            fetch('https://codesparklab.com/json/example2.json')
 6        ]);
 7        const jsonData = await fastestResponse.json();
 8        console.log('Fastest data:', jsonData);
 9    } catch (error) {
10        console.error('Fetch error:', error);
11    }
12}
13
14fetchFastestData();
  • Promise.race() returns the result of the first Promise that is either fulfilled or rejected. It is useful when you want to respond to whichever asynchronous operation completes first. However, if the first Promise fails, the error is immediately caught by catch.

Promise.allSettled()

 1async function fetchWithAllSettled() {
 2    const results = await Promise.allSettled([
 3        // This URL will success
 4        fetch('https://codesparklab.com/json/example1.json'),
 5        // This URL will fail
 6        fetch('https://invalid.codesparklab.com/')
 7    ]);
 8
 9    results.forEach((result, index) => {
10        if (result.status === 'fulfilled') {
11            const url = result.value.url;
12            console.log(`Request ${index + 1} succeeded:`, url);
13        } else {
14            const reason = result.reason;
15            console.warn(`Request ${index + 1} failed:`, reason);
16        }
17    });
18}
19
20fetchWithAllSettled();
  • Promise.allSettled() waits for all results, regardless of success or failure. Each result is returned in the form of { status, value } or { status, reason }, allowing you to determine which Promises succeeded and which failed.

Promise.any()

 1async function fetchAnySuccessful() {
 2    try {
 3        const firstSuccessful = await Promise.any([
 4            // This URL will fail
 5            fetch('https://invalid.codesparklab.com/'),
 6            // This URL will success
 7            fetch('https://codesparklab.com/json/example1.json')
 8        ]);
 9        const jsonData = await firstSuccessful.json();
10        console.log('First successful response:', jsonData);
11    } catch (error) {
12        console.error('All fetch requests failed:', error);
13    }
14}
15
16fetchAnySuccessful();
  • Promise.any() returns only the result of the first successfully fulfilled Promise. An exception is thrown only if all Promises fail. It can be used like a retry mechanism in environments where some APIs are unreliable until one succeeds.

Summary

  • async function: Always returns a Promise and is used to write asynchronous processing.
  • await: Used to wait for a Promise to resolve and receive its result.
  • Error handling: Use try...catch to handle errors that occur during asynchronous processing.
  • Multiple asynchronous operations: By using methods like Promise.all(), you can run multiple asynchronous tasks concurrently.

async/await are powerful tools for handling asynchronous processing, so be sure to utilize them to simplify complex asynchronous logic.

You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.

YouTube Video