Async/Await in JavaScript
Megan Lo
Posted on June 21, 2021
YOU ARE ALMOST THERE!!!
This will be the last article of the series.
There are 4 parts in this series:
- Intro to Asynchronous JS
-
Promises
in JavaScript - More
Promises
in JavaScript -
async
,await
(this article)
Note: If you are not familiar with the concepts of either callbacks or Promises
, I highly recommend you to visit the previous articles first. Promises
and callbacks are the precedents of async
and await
and they are the reasons why async
and await
exists.
Introduction
As mentioned in the previous article, Promises
were introduced in ES2015 and it were meant to solve the callback hell issues. Turns out Promises
were not enough. The keywords async
and await
were introduced in ES2018 to reduce the boilerplate of Promises
and to solve the limitation of "don't break the chain" in promises chaining.
Let's see the difference between Promises
and async/await
!
A promise:
const promise = () => {
return new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
})
};
async/await
:
const promise = async () => {
console.log(await promiseAsync());
};
OR
A promise:
const promise = () => {
return Promise.resolve(1);
};
async/await
:
const promise = async () => {
return 1;
};
By appending the async
keyword to any function, the function will return a promise.
Rewriting a promise with async
and await
Remember how we printed a list of Harry Potter characters from our previous article? Here's the code as a refresher:
// grab that main element
const main = document.getElementById("main");
// fetch the third-party API
// I modified this to just a fetch,
// instead of assigning to a variable
fetch("http://hp-api.herokuapp.com/api/characters")
.then(response => {
return response.json();
})
.then(characters => {
main.innerHTML = mapCharacters(characters);
});
const mapCharacters = (characters) => {
const names = characters.map(character => `<li>${character.name}</li>`);
return `<ul>${names}</ul>`
}
Let's rewrite this with aysnc/await
!
- We'll replace
.then
toawait
- We should make the function
async
for them to work!
async function fetchCharacters() {
// read JSON
let response = await fetch("http://hp-api.herokuapp.com/api/characters");
let characters = await response.json();
main.innerHTML = mapCharacters(characters);
};
fetchCharacters();
const mapCharacters = (characters) => {
const names = characters.map(character => `<li>${character.name}</li>`);
return `<ul>${names}</ul>`
}
Now we replace all the .then
with await
! It's so much cleaner and less boilerplate!!
And for error handlers, all we have to do is (unfortunately, they don't have the await
way of doing this to handle error π₯²):
fetchCharacters()
.catch(error => {
console.log(error)
});
A few things to remember
π― await
won't work in the top-level code
When we see await
inside a function, there's an async
append to the function. However, just a reminder, await
won't work in the top-level code. In other words, you can't straight up using the await
keyword on a variable:
// this won't work since it's not wrapped
// in an asynchronous function
let response = await fetch("http://hp-api.herokuapp.com/api/characters");
We have to wrap await
inside an asynchronous function.
π― You can catch errors with try...catch
One thing I didn't mention earlier in the previous article (and I apologize) is that Promise.reject(new Error("..."))
is equivalent to throw new Error("...")
.
With try...catch
, you can do this:
async function fetchCharacters() {
try {
let response = await fetch("http://hp-api.herokuapp.com/api/characters");
let characters = await response.json();
main.innerHTML = mapCharacters(characters);
} catch(err) {
console.log(err);
}
}
π― async/await
works in Promise.all
as well!!
If you came from the previous article, you might still be digesting the concept of Promise.all
. But no worries, we are only going to cover very briefly, so you have an idea.
I am going to use the example from the previous article.
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve(console.log(1)), 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve(console.log(2)), 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => resolve(console.log(3)), 3000);
});
const p4 = new Promise((resolve, reject) => {
setTimeout(() => resolve(console.log(4)), 4000);
});
const p5 = new Promise((resolve, reject) => {
reject(new Error('reject'));
});
// we wrap the promises in Promise.all and then await
let results = await Promise.all([
p1,
p2,
p3,
p4,
p5
])
That's it!!
β¨ And there you go!! β¨ Now that not only you learned Promises
, you also learned more about async/await
! Just remember with async/await
, promise.then/catch
is rarely used. async/await
together provides a great framework to write asynchronous code that is easy to read and write!
Before You Go
Since this is the last article of the series, let's end with a good note by wrapping up what we learned in this series:
- JavaScript is synchronous and single-threaded. Since JS program is typically event-driven, therefore we care about asynchronous programming.
-
Promises
were introduced in ES2015 to solve the callback-hell issue - The three states of
Promises
are pending, resolved, rejected. - When a promise object is fulfilled, the result is a value; when a promise object is rejected, the result is an error object.
- The three consumer handlers in promise:
.then
,.catch
,.finally
- We can do chain promises with
.then
- We can fetch multiple promises with
Promise.all
-
async
andawait
were introduced in ES2018 to reduce the boilerplate ofPromises
and the limitation of "don't break the chain" of chaining promises. - When
async/await
is used,promise.then/catch
is rarely used.
And that's it! I am more than happy if you need to bookmark this series for any refresher in the future!
YAY! You made it to the end! Be proud of yourself! And...
If there's any mistake or inaccuracy (with the terminology, etc.) in this series, please feel free to comment below. Like a lot of you who are reading this series, I wrote as I learned.
Hope this series help you build a foundation in asynchronous programming and get rid of the struggle before you read the series!
Last but not least, happy coding!!
Resources
π Modern Asynchronous JavaScript with Async and Await (NodeJS documentation)
π Making asynchronous programming easier with async and await (MDN)
π Async/await
π JavaScript Async/Await Tutorial β Learn Callbacks, Promises, and Async/Await in JS by Making Ice Cream π§π¨π¦
Posted on June 21, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.