关键在于识别请求依赖关系:互不依赖的异步操作应并行(用promise.all或allsettled),避免串行await拉长总耗时;依赖前序结果的才需串行。

关键不是少用 await,而是分清哪些请求必须等、哪些可以一起发。互不依赖的异步操作强行串行 await,会把总耗时拉长成各请求时间之和;改成并行,总耗时就只取决于最慢那个。
识别可并行的请求
只要后一个请求不需要前一个的结果,就属于可并行场景。比如首页加载用户信息、未读消息数、热门商品列表,三者数据来源独立、彼此无引用关系。
- ✅ 可并行:
fetchUser()、fetchUnreadCount()、fetchTrendingProducts() - ❌ 必须串行:
fetchUser()→ 拿到user.id后调fetchPosts(user.id)→ 再拿post.id调fetchComments(post.id)
用 Promise.all 替代连续 await
错误写法中,每个 await 都要等上一个完成才发起下一个,网络请求是逐个排队发出的。
正确做法是:先让所有请求“立刻启动”,再统一等待全部结果。
- 错例(串行,耗时 ≈ 300ms):
const a = await fetch('/a');<br>const b = await fetch('/b');<br>const c = await fetch('/c'); - 正例(并行,耗时 ≈ 最慢的那个,约 100ms):
const [a, b, c] = await Promise.all([fetch('/a'), fetch('/b'), fetch('/c')]);
注意:Promise.all 的参数数组里,每个 fetch() 在构造时就已执行,并非等到 await 才发请求。
循环中别在每次迭代里 await
for 或 for...of 中直接 await,本质仍是串行——上一轮没结束,下一轮根本不会开始。
- 错例:
for (const id of ids) {<br> const data = await fetch(`/item/${id}`);<br> result.push(data);<br>} - 正例(先批量发请求,再统一等):
const promises = ids.map(id => fetch(`/item/${id}`));<br>const responses = await Promise.all(promises);<br>const result = await Promise.all(responses.map(r => r.json()));
允许部分失败时改用 allSettled
Promise.all 一旦某个请求 reject,整个调用就中断,拿不到其他成功结果。如果某些接口只是辅助数据(如埋点配置、非核心推荐),可以接受个别失败,就用 Promise.allSettled。
- 返回值是数组,每项含
status('fulfilled'或'rejected')以及对应value或reason - 适合弱一致性场景,比如同时加载多个模块配置、上报日志、拉取可选卡片数据
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











