Asynchronous JavaScript and fetch
Network requests take time. JavaScript does not stop and wait; it continues and handles the result when it arrives.
Promises and async/await
async function loadUser(id) {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return response.json();
}
loadUser(1)
.then(user => console.log(user.name))
.catch(err => console.error(err));
await pauses only inside the async function; the page stays responsive.
fetch only rejects on network failure. A 404 or 500 still "succeeds", so always check response.ok.
Error handling and loading states
async function showProjects() {
list.textContent = "Loading…";
try {
const res = await fetch("/api/projects?limit=10");
if (!res.ok) throw new Error(res.status);
const projects = await res.json();
list.replaceChildren(...projects.map(p => {
const li = document.createElement("li");
li.textContent = p.title;
return li;
}));
} catch (err) {
list.textContent = "Could not load projects. Please try again.";
}
}
Sending data
const csrf = document.querySelector('meta[name="csrf-token"]').content;
const res = await fetch("/api/notes", {
method: "POST",
headers: { "Content-Type": "application/json", "X-CSRFToken": csrf },
body: JSON.stringify({ text: "Remember to deploy" }),
});
Frameworks like Flask-WTF reject POST requests without a CSRF token. PandaDev puts the token in a <meta> tag and its helper PandaDev.postJSON adds the header for you.
Running requests in parallel
const [user, orders] = await Promise.all([
fetch("/api/me").then(r => r.json()),
fetch("/api/orders").then(r => r.json()),
]);
Timeouts and cancelling
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 8000);
try {
const res = await fetch(url, { signal: controller.signal });
} finally {
clearTimeout(timer);
}
Timers
setTimeout(() => console.log("once, after 1s"), 1000);
const id = setInterval(refresh, 30000);
clearInterval(id);
Exercise
Use the public GitHub API (https://api.github.com/users/<name>/repos) to show a user's five most recently updated repositories, with a loading message, an error message for unknown users and a 10-second timeout.
Check yourself
- Why must you check
response.ok? - How do you send a CSRF token with fetch?
- When would you use
Promise.all?
ההתקדמות שלכם נשמרת בדפדפן הזה בלבד.
שליחה לבדיקה (10 נקודות)