async/await 与错误处理
这是什么:async/await = Promise 的语法糖:await 让你用同步的写法等异步结果,async 标记「这个函数里要用 await」。
为什么用:请求一多,.then 就开始套娃——then 里面再 fetch 再 then,链条越拉越长。async/await 把「等数据」写成像普通赋值一样自然,代码量砍半,还有 try/catch 这个熟悉的错误处理。
如何用:把第 2 章的两段式请求重写成 await 风格,加上加载状态和统一错误兜底,凑齐实战三件套。
重写第 2 章的请求
两段式 vs await 版,感受一下:
// 两段式(第 2 章写法)
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(res => res.json())
.then(data => console.log(data.title))
// async/await 版
async function loadPost() {
let res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
let data = await res.json()
console.log(data.title)
}
loadPost()
你会看到:两个版本打印同样的标题。await 版读起来就像「发请求,等响应;拆包,等数据」——每一步等完再走下一步,但页面照样不卡(异步的本质没变)。
| 部件 | 作用 |
|---|---|
async function |
标记这个函数里可以使用 await |
await |
等右边的 Promise 出结果,拿到值再往下走 |
| 函数返回值 | async 函数自身返回 Promise,外部要拿结果还是 .then 或 await 它 |
注意:
await必须写在 async 函数里(或<script type="module">顶层),直接在普通 script 里写会报错。
try/catch:同步写法的错误兜底
两段式的错误走 .catch,await 版走 try/catch——和 JSON 教程里 safeParse 的套路一模一样:
async function loadPost() {
try {
let res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
if (!res.ok) throw new Error('HTTP ' + res.status) // 404/500 自己抛
let data = await res.json()
console.log('标题:', data.title)
} catch (err) {
console.error('请求失败:', err.message) // 网络错误 + 主动抛的错都进这里
}
}
ok 自查 + try/catch 就是 await 时代的标准错误处理模板,.catch 的职责全由 catch 块接管。
加载状态:让用户知道「在跑了」
请求要花时间,界面上要有「加载中…」的反馈,结束时关掉——finally 是收尾的最佳位置:
async function loadUsers() {
let box = document.getElementById('app')
box.textContent = '加载中…' // ① 开始:亮出加载态
try {
let res = await fetch('https://jsonplaceholder.typicode.com/users?_limit=3')
if (!res.ok) throw new Error('HTTP ' + res.status)
let users = await res.json()
box.innerHTML = users.map(u => `<div>${u.name}</div>`).join('')
} catch (err) {
box.textContent = '加载失败:' + err.message // ② 失败:友好提示
} finally {
console.log('请求流程结束(无论成败都执行)') // ③ 收尾:关 loading、恢复按钮
}
}
loadUsers()
你会看到:先显示「加载中…」,数据到了换成三个用户名;若断网则显示失败原因。finally 在成败两种情况下都会执行,适合放「关闭加载动画、把提交按钮恢复可点」这类收尾活。
三个小坑
- await 只在 async 函数里有效——写在普通函数或全局会直接 SyntaxError
- await 的是 Promise——
await fetch(...)对,写成await res.json(没加括号)拿到的是函数不是数据 - 循环里别轻易 await——
for循环里 await 会一个接一个排队等;并发请求用Promise.all([...])一次全等齐
记忆口诀:async 配 await,异步写成同步味;try 抓错 finally 收,加载状态别浪费。
📝 本章小结
async/await用同步风格写异步:await 等 Promise 出结果,代码顺序即执行顺序- await 必须在 async 函数里;async 函数自己也返回 Promise
- 错误处理用 try/catch,
res.ok自查照旧;finally 负责收尾 - 实战三件套:加载态 + ok 自查 + try/catch,缺一不可
动手改
- 把第 4 章的 POST 请求重写成 async/await 版
- 给 loadUsers 加个「重新加载」按钮,请求期间把它设为
disabled,finally 里恢复 - 用
Promise.all同时请求/posts/1和/users/1,一起拿到结果