The async/await pattern in JavaScript, introduced as part of ECMAScript 2017 (ES8), is an absolute joy to use when working with asynchronous programming and service callbacks. It addresses the messiness of traditional promise chains with a syntax that reads more like synchronous code, making it both cleaner and easier to reason about.
This post is mostly a syntatical reference for myself (and anyone else who finds it useful) to revisit different async/await implementation patterns, from basic function calls to class methods, error handling, and batching multiple async operations.
Syntax
A simple implementation would look like this:
async function showUser(reqVal) {
const url = `https://host.com/api/user/${reqVal}`;
const response = await fetch(url);
return response.json();
}
showUser('k97').then(user => console.log(user.name));
Async implementation for an IIFE
(async () => {
const user = showUser('k97');
console.log(user.name);
})();
Class implementation
class User {
async showDetails(reqVal) {
const url = `https://host.com/api/user/${reqVal}`;
const response = await fetch(url);
return response.json();
}
}
//On implementing;
const User = new User();
const info = async User.showDetails('k97');
console.log(info);
Error handling
The errors in async can be handled using a simple try-catch block. The implmentation almost looks like a synchoronous code block execution.
async function showUser(reqVal) {
const url = `https://host.com/api/user/${reqVal}`;
const response = await fetch(url);
const body = response.json();
if(response.status !== 200) {
throw Error(body.message);
}
return body;
}
try {
const user = await onshowUser('k97');
} catch(e) {
throw new Error(e);
}
When combining this with a service call, it’s better to reject or terminate the call immediately on error, so the user receives feedback right away instead of waiting for the call to resolve unnecessarily.
Combining multiple calls
This is similar to the Promises approach, where multiple calls are stacked in an array and executed in parallel. However, using multiple await statements in a single method causes the calls to run synchronously, one after the other.
async function showUser(reqVal) {
const getUserName = await fetch(`${url}/api/${reqVal}/name`);
const getUserCountry = await fetch(`${url}/api/${reqVal}/country`);
// getUserName first fires and finishes, then the getUserCountry is processed
}
The only weird thing here is the usage of the word Promise on the resolve.
async function showUser(reqVal) {
const getUserName = fetch(`${url}/api/${reqVal}/name`);
const getUserCountry = fetch(`${url}/api/${reqVal}/country`);
try{
const {name, country} = await Promise.all([getUserName, getUserCountry]);
} catch(e) {
throw new Error(e);
}
}