显式返回Promise时是否需要为函数添加async关键字?
关于显式返回Promise时是否需要加async关键字的解答
首先纠正认知:两种写法技术层面并不完全等价
二者存在两个核心差异:
- 返回的Promise引用不同
async函数会自动把返回值包装成一个新的Promise,哪怕你显式返回一个Promise实例,最终返回的也不是你返回的那个原始实例:
const myP = new Promise(resolve => resolve(1)) const asyncFn = async () => myP const normalFn = () => myP console.log(asyncFn() === myP) // 输出 false console.log(normalFn() === myP) // 输出 true
- 同步错误的处理逻辑不同
如果函数内部有同步抛出的错误,async函数会自动把错误包装成 rejected 状态的Promise返回,而普通函数会直接同步抛出错误:
// async 写法 const wait1 = async ms => { if (typeof ms !== 'number') throw new TypeError('参数必须为数字') return new Promise(resolve => setTimeout(resolve, ms)) } wait1('abc').catch(err => console.log('捕获到错误', err)) // 正常捕获,不会中断执行 // 普通写法 const wait2 = ms => { if (typeof ms !== 'number') throw new TypeError('参数必须为数字') return new Promise(resolve => setTimeout(resolve, ms)) } wait2('abc').catch(err => console.log('捕获到错误', err)) // 直接同步抛错,中断执行,catch不生效
风格指南与规范推荐
目前行业内没有强制的统一标准,主流的实践规则如下:
- 优先加
async:绝大多数场景下,推荐给返回Promise的函数加上async关键字。一方面可以从函数定义一眼识别出这是异步函数,可读性更高;另一方面统一了错误处理逻辑,所有异常都可以通过Promise的.catch捕获,不需要同时维护同步try/catch和异步catch两套逻辑,大幅降低心智负担。 - 仅在明确符合两个条件时可以不加
async:第一,函数内没有任何同步逻辑,100%不会抛出同步错误;第二,你明确需要用到原始返回的Promise引用,或者极端高频调用的场景下需要省略一层Promise包装的微小性能开销。
补充规则:如果函数内部用到了await关键字,必须加async,这是JavaScript语法的强制要求
内容的提问来源于stack exchange,提问作者Robo Robok
相关产品推荐
相关产品推荐

