Promise和Async/Await
262 Consuming Promises with Async_Await 笔记
一、Async/Await 基础概念与核心特性
1.1 Async 函数的定义与创建
-
定义:Async 函数是一种特殊的 JavaScript 函数,通过在
function关键字前添加async关键字声明,专门用于配合 Await 关键字消费 Promise,使异步代码逻辑更接近同步代码的直观形式。 -
创建语法:
1
2
3
4
5
6
7
8
9// 函数声明式
async function fetchData() {
// 函数体(可包含 await 语句)
}
// 箭头函数式
const fetchData = async () => {
// 函数体(可包含 await 语句)
}; -
核心特性:
- 自动返回 Promise:无论 Async 函数内部返回什么值(非 Promise 类型值会被自动包装成已resolved的 Promise),函数最终的返回结果一定是 Promise 对象。例如:
1
2
3
4async function getNum() {
return 10; // 等价于 return Promise.resolve(10)
}
getNum().then((res) => console.log(res)); // 输出:10 - 后台异步执行:Async 函数调用后,会在 JavaScript 事件循环的后台队列中执行,不会阻塞主线程(调用栈)的正常执行,避免页面卡顿或功能冻结。
- 自动返回 Promise:无论 Async 函数内部返回什么值(非 Promise 类型值会被自动包装成已resolved的 Promise),函数最终的返回结果一定是 Promise 对象。例如:
1.2 Await 关键字的作用与使用规则
- 定义:
await是仅能在 Async 函数内部使用的关键字,用于“等待”一个 Promise 对象的状态变更(从 pending 变为 resolved 或 rejected),并获取 Promise resolved 后的结果。 - 使用规则:
- 仅能在 Async 函数内使用:若在非 Async 函数中使用
await,会直接触发语法错误。1
2
3
4// 错误示例:非 Async 函数中使用 await
function wrongFunc() {
await fetch('https://api.example.com'); // Uncaught SyntaxError: await is only valid in async functions
} - 右侧需是 Promise 对象:若
await右侧不是 Promise,会将其视为已 resolved 的 Promise,直接返回该值。例如:1
2
3
4
5async function getValue() {
const result = await "hello"; // 等价于 await Promise.resolve('hello')
console.log(result); // 输出:hello
}
getValue();
- 仅能在 Async 函数内使用:若在非 Async 函数中使用
- 执行逻辑:
await会暂停当前 Async 函数内部的代码执行(注意:仅暂停函数内部,不阻塞主线程),直至 Promise 状态变更:- 若 Promise resolved:
await表达式的结果为 Promise 的 resolved 值,函数继续执行后续代码; - 若 Promise rejected:需配合
try/catch捕获错误(后续“错误处理”章节详解),否则会触发未捕获的 Promise 错误。
- 若 Promise resolved:
二、Async/Await 消费 Promise 实战案例
2.1 基础案例:使用 Async/Await 调用 API 获取数据
场景需求
通过 fetch 调用“国家信息 API”,获取指定国家(如葡萄牙)的信息,并打印响应结果,验证 Async 函数的异步特性。
实现代码
1 | // 1. 定义 Async 函数,用于获取国家数据 |
执行结果与分析
1 | 开始调用获取国家数据的函数 |
- 结果分析:先打印“开始调用”和“调用已发起”,再打印 API 响应和解析后的数据,证明 Async 函数在后台异步执行,未阻塞主线程的同步代码(调用前后的
console.log)。
2.2 进阶案例:Async/Await 处理 Promise 链(地理定位 + 反向地理编码)
场景需求
- 通过浏览器
navigator.geolocation.getCurrentPosition获取用户当前地理位置(需先“Promise 化”该回调式 API); - 用获取到的经纬度调用“反向地理编码 API”,获取用户所在国家;
- 用获取到的国家名称,调用“国家信息 API”,最终打印完整的国家数据。
前置步骤:Promise 化回调式 API(地理定位)
navigator.geolocation.getCurrentPosition 是传统回调式 API(非 Promise 风格),需先封装为 Promise,才能用 Await 消费:
1 | // 封装地理定位 API 为 Promise |
完整实现代码
1 | // 1. Promise 化地理定位 API(同上) |
代码优势分析
- 对比传统
then链:无需嵌套then回调(避免“回调地狱”),代码按“步骤1→步骤2→步骤3”的线性逻辑编写,可读性大幅提升; - 错误统一处理:通过
try/catch捕获整个异步流程中的所有错误(包括地理定位失败、API 请求超时等),无需在每个then后加catch。
三、Async/Await 关键注意事项与本质
3.1 Async/Await 的本质:Promise 的语法糖
- 核心结论:Async/Await 并非新的异步机制,而是“消费 Promise 的语法糖”——底层仍依赖 Promise 和 JavaScript 事件循环,只是简化了 Promise 的调用写法。
- 等价对比:Async/Await vs then 链
以“获取国家数据并解析 JSON”为例,两种写法等价:- Async/Await 写法:
1
2
3
4
5async function fetchCountry() {
const res = await fetch("https://restcountries.com/v3.1/name/portugal");
const data = await res.json();
console.log(data);
} - 传统 then 链写法:
1
2
3
4
5function fetchCountry() {
fetch("https://restcountries.com/v3.1/name/portugal")
.then((res) => res.json())
.then((data) => console.log(data));
}
- Async/Await 写法:
- 注意:使用 Async/Await 的前提是理解 Promise 的底层逻辑(如 pending/resolved/rejected 状态、事件循环),否则可能无法排查隐藏的异步错误。
3.2 未处理错误的风险与临时解决方案
风险场景
若 Async 函数中 await 的 Promise 被 rejected(如 API 请求超限、网络中断),且未做错误处理,会触发“未捕获的 Promise 错误”,导致代码崩溃。
例如:反向地理编码 API 限制“每秒仅 3 次请求”,若快速刷新页面多次调用,会返回 429 错误:
1 | async function getGeoData(lat, lng) { |
临时解决方案:try/catch 捕获错误
在 Async 函数内部用 try/catch 包裹所有 await 语句,统一捕获错误:
1 | async function getGeoData(lat, lng) { |
四、总结与核心考点
4.1 核心知识点总结
- Async 函数:用
async声明,自动返回 Promise,后台异步执行,不阻塞主线程; - Await 关键字:仅在 Async 函数内使用,等待 Promise 状态变更,获取 resolved 结果,暂停函数内部执行但不阻塞主线程;
- 实战优势:简化 Promise 链(替代
then嵌套),代码逻辑线性化,错误处理统一(try/catch); - 本质与前提:是 Promise 的语法糖,使用前需理解 Promise 和事件循环,否则易踩坑。
4.2 常见考点与例题
例题1:判断代码执行顺序
请写出以下代码的输出顺序:
1 | console.log("1"); |
答案与解析
输出顺序:1 → 2 → 4 → 3
- 解析:
console.log('1')是同步代码,先执行;- 调用
asyncFunc(),同步执行函数内的console.log('2'); await等待 Promise(定时器 1 秒后 resolve),暂停asyncFunc内部执行,将后续代码(console.log('3'))放入微任务队列;- 主线程继续执行同步代码
console.log('4'); - 1 秒后定时器触发,Promise resolve,
console.log('3')从微任务队列进入主线程执行。
例题2:Async 函数返回值处理
以下代码中,result 的值是什么?
1 | async function getResult() { |
答案与解析
result 的值是 'success'
- 解析:Async 函数内部返回非 Promise 值时,会自动包装成
Promise.resolve('success'),因此then中获取的res就是'success'。
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自木鱼的鱼窝


