JavaScript Fundamentals

Asynchronous JavaScript and fetch

40 分钟

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 积分)