理解 async 和 await 的核心概念,学会编写类同步风格的异步代码。
掌握 async 函数的特性:始终返回 Promise 以及自动包装非 Promise 返回值。
熟练使用 await 关键字暂停执行以等待 Promise 结算,消除回调嵌套。
运用 try...catch 块优雅地处理异步操作中的错误,替代繁琐的 .catch() 链。
在 JavaScript 中,Async/Await 是建立在 Promise 之上的语法糖。它允许开发者以同步代码的写法来处理异步逻辑,极大地提升了代码的可读性、可理解性和可维护性。
代码清晰: 避免了 .then() 和 .catch() 的链式调用,逻辑流程一目了然。
错误处理简化: 可以使用传统的 try...catch 语句捕获异步错误。
非阻塞执行: 虽然写法像同步,但底层依然是非阻塞的,不会卡住主线程。
结构化流程: 非常适合管理复杂的异步业务逻辑(如顺序依赖的多个 API 请求)。
async function fetchData() {
try {
// 模拟一个已解决的 Promise ( mock 数据)
const response = await Promise.resolve({
json: async () => ({
userId: 1,
id: 1,
title: "示例文章",
body: "这是用于演示 async/await 的模拟数据"
})
});
// 等待 json() 方法解析完成
const data = await response.json();
console.log(data);
} catch (error) {
console.error("获取数据时出错:", error);
}
}
fetchData();async 关键字用于声明一个异步函数。它让基于 Promise 的代码看起来像同步代码,同时保持执行的非阻塞特性。
始终返回 Promise:
无论函数内部返回什么值,async 函数都会自动将其包装在一个 Promise 中。
如果返回的是普通值,等价于 Promise.resolve(value)。
如果返回的是一个已被拒绝的 Promise 或抛出错误,等价于 Promise.reject(error)。
非阻塞: 函数内部的 await 只会暂停该函数内部的执行,不会阻塞浏览器的其他操作(如 UI 渲染、其他事件响应)。
无缝配合 Await: 只有在 async 函数内部才能使用 await 关键字。
// 声明方式 1: 函数声明
async function myFunction() {
return "Hello"; // 实际返回 Promise.resolve("Hello")
}
// 声明方式 2: 箭头函数
const getData = async () => {
let data = "Hello World";
return data; // 实际返回 Promise.resolve("Hello World")
};
// 调用验证
getData().then(data => console.log(data));
// 输出: Hello World注意: 即使你直接
return "字符串",外部调用时也必须使用.then()或await来获取值,因为返回值本质上是一个 Promise。
await 关键字用于暂停 async 函数的执行,直到等待的 Promise 对象结算(resolved 或 rejected)。
仅限内部使用: await 只能在 async 函数内部使用。在全局作用域或非 async 函数中使用会报错(注:现代浏览器顶部层级支持 Top-level Await,但在函数体内仍是主流用法)。
暂停而非阻塞: 它暂停的是当前 async 函数的后续代码执行,让出主线程去处理其他任务,直到 Promise 有结果后恢复执行。
获取结果: await 表达式的值就是 Promise resolve 后的值。如果 Promise 被 reject,则会抛出异常。
const getData = async () => {
// 等待一个立即解决的 Promise (或者普通值,会被自动包装)
let y = await "Hello World";
console.log(y);
};
console.log(1); // 1. 首先执行
getData(); // 2. 调用 async 函数,开始执行直到遇到 await
console.log(2); // 3. 主线程继续执行,打印 2 (此时 getData 内部暂停)
// 4. 微任务队列中的 getData 恢复,打印 "Hello World"输出顺序:
1
2
Hello World
原理解析:
async 将函数转换为返回 Promise 的异步函数。
await 让函数“暂停”在此行,将后续代码放入微任务队列。
主线程不受影响,继续执行 console.log(2)。
当 Promise 结算后,函数恢复执行并打印结果。
在 Promise 链式调用中,我们使用 .catch() 处理错误。而在 async/await 中,推荐使用标准的 try...catch 语句,这使得错误处理逻辑更加直观和集中。
Resolve: 当异步任务成功完成时,await 返回结果值。
Reject: 当异步任务失败时,await 会抛出一个异常,该异常可以被外层的 try...catch 捕获。
网络请求处理
async function fetchData() {
try {
// 1. 发送 HTTP 请求并等待响应
// 如果网络断开或 URL 错误,fetch 会 reject,此处直接跳转到 catch
let response = await fetch('https://api.example.com/data');
// 2. 检查 HTTP 状态码 (fetch 只有网络错误才会 reject,404/500 需手动处理)
if (!response.ok) {
throw new Error(`HTTP 错误!状态码:${response.status}`);
}
// 3. 解析 JSON 数据并等待解析完成
let data = await response.json();
// 4. 成功获取数据
console.log("获取到的数据:", data);
} catch (error) {
// 5. 统一捕获所有错误(网络错误、JSON 解析错误、手动抛出的错误)
console.error('获取数据失败:', error.message);
}
}
fetchData();await fetch(...): 发起请求。若发生网络故障,Promise 被 reject,控制权立即转移到 catch 块。
await response.json(): 解析 body。若返回内容不是合法 JSON,会抛出异常,同样被 catch 捕获。
try...catch: 包裹整个异步流程,任何一步出错都能被统一处理,避免了在每个 .then() 后都写 .catch() 的冗余。