0Pricing
Frontend Academy · 课时

async/await 与错误处理

使用 await 关键字编写异步函数,将等待调用放在 try/catch 代码块中,并理解 async/await 如何以语法糖的形式实现 Promise。

async/await 与错误处理 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。

什么是 async/await?

async/await 是 Promise 之上的语法糖。async 函数始终返回 Promise。await 关键字会暂停函数,直到等待的 Promise 确定状态。代码看起来像同步代码,但实际会异步运行。

async 函数

请在函数声明或表达式前添加 async 关键字。这样,该函数就会自动将返回值包装在 Promise 中。

async function fetchUser(id) {
  // implicitly returns a Promise
  return { id, name: 'Alice' };
}

// Equivalent to:
function fetchUser(id) {
  return Promise.resolve({ id, name: 'Alice' });
}

await——暂停等待 Promise

await 只能在 async 函数中使用。它会暂停执行,直到 Promise 完成,然后返回已解析的值。事件循环中的其他代码会继续运行。

async function loadProfile(id) {
  const user = await fetchUser(id);     // waits for Promise
  const posts = await fetchPosts(user.id); // waits again
  return { user, posts };
}

顺序等待与并行等待

按顺序等待更容易阅读,但如果任务之间互不依赖,速度会较慢。请使用 Promise.all() 来并行等待多个相互独立的任务。

// Sequential (slow if tasks are independent):
const user = await fetchUser(id);
const settings = await fetchSettings(id); // waits for user unnecessarily

// Parallel (fast):
const [user, settings] = await Promise.all([
  fetchUser(id),
  fetchSettings(id),
]);

使用 try/catch 处理错误

请将等待调用放在 try/catch 中,以处理拒绝。catch 代码块会将拒绝原因作为错误对象接收。

async function saveUser(data) {
  try {
    const response = await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' }
    });
    if (!response.ok) throw new Error(`Server error ${response.status}`);
    return await response.json();
  } catch (err) {
    console.error('Save failed:', err.message);
    throw err; // re-throw so caller can handle
  }
}

顶层 await

在 ES 模块中(而不是 CommonJS 中),您可以在顶层直接使用 await,无需将其包裹在异步函数中。这对于模块初始化很有用。

// module.js (ES module)
const config = await fetch('/config.json').then(r => r.json());
export const API_URL = config.apiUrl;

async/await 与 forEach——易错点

Array.forEach() 不会等待异步回调。请使用 for...of 进行顺序异步迭代,或使用 Promise.all(arr.map(...)) 进行并行处理。

// WRONG — forEach doesn't await:
items.forEach(async (item) => {
  await processItem(item); // runs but forEach doesn't wait
});

// CORRECT — sequential:
for (const item of items) {
  await processItem(item);
}

// CORRECT — parallel:
await Promise.all(items.map(item => processItem(item)));

错误对象与自定义错误

请始终抛出错误对象,而不是字符串,以便保留堆栈跟踪。请为特定领域的错误创建自定义错误类,以便调用方可以按类型捕获它们。

class NetworkError extends Error {
  constructor(message, status) {
    super(message);
    this.name = 'NetworkError';
    this.status = status;
  }
}

try {
  const res = await fetch(url);
  if (!res.ok) throw new NetworkError(`Failed`, res.status);
} catch (err) {
  if (err instanceof NetworkError && err.status === 401) {
    redirectToLogin();
  } else {
    throw err;
  }
}

async/await 中的 finally

finally 代码块无论 try 成功还是失败都会运行,就像 Promise 上的 .finally() 一样。请使用它来释放资源或隐藏加载状态。

async function loadData() {
  setLoading(true);
  try {
    const data = await fetch('/api/data').then(r => r.json());
    setData(data);
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false); // always runs
  }
}

模块入口点的异步 IIFE

当无法使用顶层 await 时,请将脚本的入口点包裹在异步 IIFE 中。

(async () => {
  const data = await fetchInitialData();
  renderApp(data);
})();

使用 AbortController 取消操作

请将 AbortController 信号传递给 fetch,以取消正在进行的请求。单独捕获 AbortError 可以避免向用户显示错误。

const controller = new AbortController();

try {
  const data = await fetch(url, { signal: controller.signal }).then(r => r.json());
  setData(data);
} catch (err) {
  if (err.name !== 'AbortError') setError(err.message);
}

// Cancel:
controller.abort();

快速检查

哪种结构可以正确处理等待中的 Promise 所产生的错误?

回顾:async/await

async 函数始终返回 Promise。await 会暂停执行,直到 Promise 确定状态。请使用 try/catch 处理错误。对于并行操作,请使用 Promise.all()。避免在 forEach 中使用 await——请改用 for...of 或 Promise.all。AbortController 可以取消正在进行的请求。顶层 await 可在 ES 模块中使用。

常见问题解答

「async/await 与错误处理」课时是免费的吗?

是的 — 「async/await 与错误处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。

「async/await 与错误处理」这节课中我会学到什么?

使用 await 关键字编写异步函数,将等待调用放在 try/catch 代码块中,并理解 async/await 如何以语法糖的形式实现 Promise。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Frontend Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「async/await 与错误处理」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Frontend Academy 课中编写并运行代码吗?

能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 事件循环:调用栈、队列与微任务
  2. 回调与回调地狱
  3. Promise:then、catch、finally 与 Promise.all
  4. async/await 与错误处理
← 返回 Frontend Academy