Promises and Async/Await
When you need to work with asynchronous operations, you usually have to deal with promise objects. A promise is an object that might deliver data at a later point in the program, or it might crash and deliver an error instead.
An example of an async function that returns a promise is the Web fetch
API that’s natively available in some browsers.
const fetchData = () => { fetch('https://api.github.com').then(resp => { resp.json().then(data => { console.log(data); }); }); };
The fetchData
function fetches information from the top-level GitHub API. Since fetch
returns a promise, to consume that promise we do a .then
call on the result of fetch
and supply a callback function in there. The callback function will receive the raw response from the API. If you need to parse the data as JSON, you need to call the json()
method on the raw response object. That json()
method is also an asynchronous one, so it returns a promise as well. To get to the data, you need another .then
call on the result of the json()
method and in the callback of that you can access the parsed data.
As you can see, this syntax might get complicated with more nesting of asynchronous operations or when you need to combine this with any looping logic. You can simplify the nesting above by making each promise callback return the promise object, but the whole .then
syntax is a bit less readable than the modern way to consume promises in JavaScript which is using async/await
:
const fetchData = async () => { const resp = await fetch('https://api.github.com'); const data = await resp.json(); console.log(data); };
You just await
on the async call (the one that returns a promise) and that will give you back the response object directly. Then, you can await
on the json()
method to access the parsed JSON data. To make await
calls work, you need to label the function as async
.
The async/await syntax is just another way for you to consume promises (but without having to deal with .then
calls). It’s a bit simpler to read but keep in mind that once you await on anything in a function that function itself becomes asynchronous and it will return a promise object (even if you don’t return anything from it).
For error-handling (when promises reject, for example) you can combine the async/await syntax with the plain-old try/catch statement (and you should do that all the time).