调用API时async/await的优势及依赖场景使用问题
调用API时使用async/await的优势
- 代码逻辑和同步写法一致,线性可读,不用嵌套多层
.then()回调,不会出现回调地狱问题,调试时调用栈清晰,打断点排查问题的成本低很多。 - 错误处理逻辑统一,可以直接用
try/catch块同时捕获代码里的同步报错和异步Promise的reject异常,不用给每个异步请求单独绑定.catch(),漏处理异常的概率更低。 - 处理复杂异步分支更方便,比如需要根据前一个接口的返回值判断是否要调用后续接口、循环中按顺序调用接口这类场景,不用在回调里嵌套多层判断,代码可维护性更高。
- 并发控制简单,配合
Promise.all、Promise.allSettled等方法,可以很方便地实现多个无依赖接口并发请求、全部完成后统一处理的逻辑,比纯Promise链式调用简洁很多。
异步数据依赖后续逻辑时的async/await正确用法
核心原则非常明确:所有依赖API返回结果的逻辑,必须放在对应await语句的后方,保证时序上await等待的Promise已经落定(要么成功返回、要么抛出错误)之后,再执行依赖数据的逻辑。
如果多个API之间没有依赖关系,不要串行写多个await(会让接口按顺序排队,总耗时是所有接口耗时之和),用Promise.all把多个API请求包成一个Promise并发执行,等所有接口都返回后再走后续逻辑,能大幅缩短总等待时间。
针对示例代码的问题解答
首先先纠正示例代码里的两个语法错误:
Promise.all是内置函数,调用时需要用圆括号传参,原代码写的方括号是语法错误- 数组内的元素需要用逗号分隔,不能写分号
修正语法后的基础代码结构如下:
let names = []; async function foo() { await Promise.all([ this.callAPI1(), this.callAPI2() ]); this.updateNames(names); }
针对两个具体疑问:
- 只要
callAPI1、callAPI2是正确实现的异步函数(即返回Promise,且Promise会在内部往names数组推入名称的操作全部完成后才resolve),updateNames绝对不会在API调用完成前执行。await关键字会暂停当前async函数的执行,让出线程给其他任务,等后面的Promise全部resolve之后,才会回到这个函数继续执行后续代码,时序是完全可控的。 - 完全不需要阻塞运行时改成同步执行。JS是单线程模型,如果把API调用改成同步阻塞,等待接口返回的整个过程中,线程会被完全占住:前端环境下页面会直接卡死,用户点击、滚动所有操作都没有响应;Node环境下事件循环会被阻塞,所有其他请求、定时任务都会排队等待,性能极差。
await + Promise.all的写法已经能保证正确的执行时序,同时等待接口的过程中线程还能正常处理其他任务,是这类场景的标准最优写法。
注意:如果
callAPI1/callAPI2内部写了异步操作但是没有正确返回对应Promise(比如发了请求没return、用setTimeout往names推数据但是没包成Promise返回),会出现await等不到内部操作完成、updateNames提前执行的问题,这时候需要修正API函数的实现,保证返回的Promise状态和内部异步操作的完成时机对齐,而不是改成同步代码。
内容的提问来源于stack exchange,提问作者sal3jfc
相关产品推荐
相关产品推荐

