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 反馈 — 无需本地设置。
此课程中的所有课时
- 事件循环:调用栈、队列与微任务
- 回调与回调地狱
- Promise:then、catch、finally 与 Promise.all
- async/await 与错误处理