Quiz

What is async/await and how does it simplify asynchronous code?

Topics
AsyncJavaScript

TL;DR

async/await is a modern syntax in JavaScript that simplifies working with promises. By using the async keyword before a function, you can use the await keyword inside that function to pause execution until a promise is resolved. This makes asynchronous code look and behave more like synchronous code, making it easier to read and maintain.

async function fetchData() {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts/1',
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();

Suspension and resumption

await pauses only the current async function; it does not block the JavaScript thread or make the surrounding caller wait synchronously.

Async function suspension at await

The resumed code runs as a promise reaction, so it follows microtask ordering.

What is async/await and how does it simplify asynchronous code?

Introduction to async/await

async/await is a feature introduced in ECMAScript 2017 (ES8) that allows you to write asynchronous code in a more synchronous-looking manner. It is built on top of promises and provides a cleaner and more readable way to handle asynchronous operations.

Using the async keyword

The async keyword is used to declare an asynchronous function. When a function is declared as async, it automatically returns a promise. This means you can use the await keyword inside it to pause the execution of the function until a promise is resolved.

async function exampleFunction() {
return 'Hello, World!';
}
exampleFunction().then(console.log); // Output: Hello, World!

Using the await keyword

The await keyword can be used inside an async function and at the top level of an ES module. It suspends that async function or module until the value is fulfilled; it does not block the JavaScript thread. If the awaited promise rejects, await throws that reason, which can be caught with try...catch.

async function fetchData() {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts/1',
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();

Simplifying asynchronous code

Before async/await, handling asynchronous operations often involved chaining multiple .then() calls, which could lead to "callback hell" or "pyramid of doom." async/await flattens this structure, making the code more readable and easier to maintain.

Example with promises

fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error('Error fetching data:', error);
});

Example with async/await

async function fetchData() {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts/1',
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();

Error handling

Error handling with async/await is more straightforward compared to promises. You can use try...catch blocks to handle errors, making the code cleaner and more intuitive.

async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicod.com/posts/1'); // Typo in URL
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise
Check your understanding Exercise

What does this code log?

async function load() {
try {
const value = await Promise.reject(new Error('nope'));
return value;
} catch (error) {
return error.message;
} finally {
console.log('cleanup');
}
}
load().then(console.log);
console.log('sync');