async/await and Fetching Data
What You Will Learn
So far, you have seen promises — objects that represent a value arriving later. In this chapter you learn async/await, a way to write asynchronous code that looks almost like normal, step-by-step code. You will also fetch data from a web address, the most common real-world use of async/await.
Prerequisites
This chapter assumes you know what a promise is and how to use .then(). You should also know basic function syntax.
Two New Keywords
async is a keyword you put before a function. It means the function always returns a promise.
await is a keyword you put before a promise. It means "pause here until the promise is settled, then give me the result." You can only use await inside an async function.
Here is a promise-based example rewritten with async/await:
// Old way, with .then()
function wait() {
return new Promise(resolve => setTimeout(resolve, 1000));
}
wait().then(() => console.log('done'));
// New way, with async/await
async function run() {
await wait(); // pause here for 1 second
console.log('done');
}
run();The await version reads top to bottom, which makes it easier to follow.
Fetching Data
fetch is a built-in browser function that requests data from a web address (a URL, such as https://api.example.com/users/1). It returns a promise for the server's response. A response is an object describing what the server sent back.
async function loadUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
}Step by step:
await fetch(...)— send the request and wait for the response headers.response.ok— a boolean that istrueonly when the HTTP status code is 200–299. A status code is a number the server sends, like 200 for "OK" or 404 for "not found."fetchdoes not throw an error on a 404, so you must check this yourself.throw new Error(...)— if the request failed, raise an error so the caller can handle it.response.json()— this reads the response body and turns the JSON text (a common data format that looks like JavaScript objects) into a real JavaScript value. It also returns a promise, so it needsawaittoo.
Catching Errors
Errors from await are caught with a normal try/catch block, which you met earlier:
async function showUser(id) {
try {
const user = await loadUser(id);
console.log(user);
} catch (error) {
console.log('Could not load user:', error.message);
}
}
showUser(1);How It Flows
Show diagram source
sequenceDiagram
participant C as Caller
participant A as async function
participant S as Server
C->>A: call showUser(1)
A->>S: fetch request
S-->>A: response (status 200)
A->>A: check response.ok
A->>S: response.json()
S-->>A: parsed data
A-->>C: return data
Note over C,A: error? catch block runs insteadCommon Mistakes
- Forgetting
await.fetch(url)withoutawaitgives you a promise, not the data. Logging it showsPromise { <pending> }. - Forgetting
awaitonresponse.json(). You get a promise for the data, not the data. - Skipping the
response.okcheck. A 404 error will look like success andresponse.json()will fail confusingly.
Practice
Exercise
What does await do, and where can you use it?
Show answer
await pauses the async function until the promise settles, then gives you the settled value (or throws if the promise rejected). You can only use it inside an async function.
Exercise
fetch succeeds but the server returned status 404. Does fetch throw an error? What should you do?
Show answer
No, fetch does not throw for HTTP error statuses. You should check response.ok and throw your own error if it is false.
Spotted a mistake, or code that does not work?