在JavaScript中已有Promise.all时为什么还要使用async await?
核心结论
Promise.all 和 async/await 并不是互斥的替代关系,二者解决的是完全不同的异步场景问题,甚至在大部分复杂业务逻辑中会搭配使用。
1. 二者的核心定位完全不同
Promise.all是专门用来处理多个无依赖的并行异步任务的工具:当你有一批互相独立的Promise,需要等所有任务都完成后再执行后续逻辑时才会用到它,它本身的返回值也是一个Promise实例。- async/await 是Promise的语法糖,解决的是所有异步代码的同步化书写体验问题:不管是串行异步任务、混合并行串行的复杂流程,还是需要加入条件、循环判断的异步逻辑,都可以用async/await写得和普通同步代码结构一致,大幅提升可读性。
典型场景:串行异步依赖(Promise.all完全无法处理)
当你的异步任务之间有强依赖,后一个请求需要前一个请求的返回值作为参数时,Promise.all 完全没有用武之地,这种场景下async/await的优势会非常明显:
// Promise链式写法,层级深了之后可读性非常差 fetch('/api/current-user') .then(res => res.json()) .then(user => fetch(`/api/user-orders?uid=${user.id}`)) .then(res => res.json()) .then(orders => fetch(`/api/order-detail?orderId=${orders[0].id}`)) .then(res => res.json()) .then(detail => console.log(detail)) .catch(err => console.error(err))
用async/await改写后逻辑完全扁平化,和同步代码的阅读逻辑没有区别:
// async/await写法 async function getFirstOrderDetail() { try { const userRes = await fetch('/api/current-user') const user = await userRes.json() const ordersRes = await fetch(`/api/user-orders?uid=${user.id}`) const orders = await ordersRes.json() const detailRes = await fetch(`/api/order-detail?orderId=${orders[0].id}`) const detail = await detailRes.json() console.log(detail) } catch (err) { console.error(err) } }
2. 复杂流程中二者可以搭配使用
遇到既有串行依赖,又有并行批量请求的场景,二者搭配使用是最优解:
比如你拿到用户的全部订单后,需要同时拉取所有订单的物流信息,就可以这么写:
async function getAllOrderLogistics() { // 串行获取用户、订单数据 const userRes = await fetch('/api/current-user') const user = await userRes.json() const ordersRes = await fetch(`/api/user-orders?uid=${user.id}`) const orders = await ordersRes.json() // 并行拉取所有订单的物流信息,用Promise.all + await直接拿到结果 const logisticsList = await Promise.all( orders.map(order => fetch(`/api/logistics?orderId=${order.id}`).then(res => res.json())) ) return logisticsList }
3. async/await独有的场景优势
- 异常处理更符合直觉:可以用原生的
try/catch统一捕获所有异步环节的异常,不需要处理Promise链式调用的错误冒泡边界问题,也不用给每个.then单独加错误回调。 - 灵活支持带流程控制的异步逻辑:如果需要在异步流程中加条件判断、循环等逻辑,用async/await写和写同步代码没有任何区别,比如循环分页拉取全量数据的场景,用Promise链式写会非常繁琐,用async/await就非常直观:
async function getAllListData() { let page = 1 let fullList = [] while(true) { const res = await fetch(`/api/goods-list?page=${page}`) const pageData = await res.json() if(pageData.length === 0) break fullList = fullList.concat(pageData) page++ } return fullList }
内容的提问来源于stack exchange,提问作者Mohammed Ajaas
相关产品推荐
相关产品推荐

