JavaScript函数返回Promise时,用async替代try/catch是否存在弊端?
问题
我有一个可能抛出异常的函数,执行成功时会返回Promise。我希望在后续代码的同一个catch块中处理函数异常或Promise拒绝。
我可以在函数中添加try块,捕获异常后返回rejected Promise,示例代码如下:
function foo(x) { try { // code here may throw an exception return myPromise(x.y) } catch (ex) { return Promise.reject(ex) } }
之后可通过foo(x).catch(ex => { /* handler here */})进行处理。
另一种方式是将函数声明为async,这样函数中的任何异常都会使foo()返回的Promise变为拒绝状态,示例代码如下:
async function foo(x) { // code here may throw an exception return myPromise(x.y) }
同样可以按之前的方式处理异常和拒绝,请问第二种方式存在哪些弊端?
回答
- 额外的Promise包装开销:async函数会强制把内部返回的结果(哪怕已经是Promise)再包装一层Promise。虽然绝大多数场景下这种性能损耗可以忽略,但在需要高频调用的场景中,可能会积累出细微的性能差异。
- 老旧环境兼容性不足:async/await是ES2017引入的语法特性,完全不支持IE11及更早版本的浏览器。如果你的代码需要兼容这类旧环境,async写法就无法使用,而手动try/catch+返回rejected Promise的方式兼容性更广。
- 调试栈信息更复杂:async函数抛出的异常会在调用栈中带上async函数的额外栈帧,有时候会增加定位原始异常位置的成本,需要多一步解析才能找到真正的异常抛出点;而手动捕获的方式,异常栈更贴近原始代码的执行路径。
- 返回值类型的强制包装:如果后续代码修改导致函数某些分支返回非Promise值,async函数会自动把它包装成Promise,而手动写法可以根据需求灵活控制返回值类型(当然这一点在当前你的场景中不存在,但属于async函数特性带来的潜在差异)。
内容的提问来源于stack exchange,提问作者morne
相关产品推荐
相关产品推荐

