Promises and async await

A common way to write asynchronous JavaScript is using a pattern called Promises. Promises are a feature of ES6 JavaScript.

function wait(timeMilliseconds = 1000) {
return new Promise((resolve) => {
window.setTimeout(() => resolve(), timeMilliseconds);
});
}

You can wait for a Promise to complete and do further operations using the then() function of the Promise:

wait(2000).then(() => {
console.log('Time is up!');
});

Errors in promises are handled via .catch(). Below, you can see common use-case for promises, which is for fetching data:

function fetchUsers() {
return new Promise((resolve, reject) => {
fetch('/api/users')
.then(response => response.json())
.then(data => resolve(data))
.catch(err => reject(err));
});
}

async/await

Working a lot with promises can lead to a pyramid of doom:

wait(2000).then(() => {
console.log('2 seconds');
wait(2000).then(() => {
console.log('4 seconds');
wait(2000).then(() => {
console.log('6 seconds');
wait(2000).then(() => {
console.log('8 seconds');
wait(2000).then(() => {
console.log('10 seconds');
});
});
});
});
});

This can become difficult to maintain. That's why there is an alternative way: async functions and await.

const tenSeconds = async () => {
for (let i = 1; i <= 10; i++) {
await wait(1000);
console.log(`${i} seconds.`);
}
};

An async function is a function that returns a promise. Inside async functions, you can use await to wait for a Promise to be completed. await can only be used inside async functions. You can still call an async function directly, but then you don't have any control about when the function completes.

Error handling inside async functions

For error-handling, try-catch is used.

const main = async () => {
try {
const users = await fetchUsers();
} catch(err) {
console.error(err.message);
}
}

main();

Awaiting multiple promises in parallel

You can use await with Promise.all:

const [users, posts] = await Promise.all([fetchUsers, fetchPosts]);

Return types

An asynchronous function in JavaScript always returns a Promise, even if it doesn't contain any asynchronous code:

const asyncFunction = async (): Promise<void> => {};

const asyncFunctionReturningAnswer = async (): Promise<number> => 42;