Asynchronous JavaScript and Fetch
JavaScript runs on a single thread. Slow work (network, timers) is asynchronous: it is started, and its callback runs later via the event loop.
console.log("1");
setTimeout(() => console.log("3"), 0);
Promise.resolve().then(() => console.log("2"));
console.log("4");
// 1, 4, 2, 3 (microtasks run before timers)
Promises and async/await
function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function run() {
console.log("start");
await wait(500);
console.log("done after 500ms");
}
run();
Fetch API
async function loadUser(id) {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`); // fetch does not throw on 404/500
}
return response.json();
}
try {
const user = await loadUser(42);
console.log(user.name);
} catch (err) {
console.error("Failed:", err.message);
}
Sending JSON
await fetch("/api/notes", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: "Learn async" }),
});
Parallel requests
const [users, posts] = await Promise.all([
fetch("/api/users").then((r) => r.json()),
fetch("/api/posts").then((r) => r.json()),
]);
Promise.all fails fast; Promise.allSettled waits for every result.
Good practices
- Always handle errors and show loading and error states in the UI.
- Cancel stale requests with
AbortController. - Do not trust the response shape: validate it.
- Remember CORS: the server must allow cross-origin browser requests.
Loading Comments...