为何在try/catch中捕获到的是已拒绝的Promise而非其拒绝时传入的Error?
这个问题的核心原因出在你对async函数的返回值和Promise的reject参数理解上,咱们一步步拆解:
问题根源:async函数的返回特性
你定义的processAjaxError是一个async函数,但它内部并没有任何异步操作,只是创建了一个Error实例并返回。而async函数的本质是:无论你return什么值(包括Error),都会自动将其包装成一个状态为resolved的Promise。
所以当你执行:
let error = processAjaxError(...arguments);
这里的error并不是你创建的Error实例,而是一个已经resolved的Promise,它的PromiseResult才是那个Error。
接下来你把这个Promise直接传给了reject(error),这就导致doSomethingAsync返回的Promise被拒绝时,它的拒绝原因就是这个resolved的Promise。当你用await调用doSomethingAsync(event)时,catch块捕获到的自然就是这个作为拒绝原因的Promise,而非里面的Error。
解决方案
根据你的实际需求,有两种修正方式:
方案1:将processAjaxError改为普通函数(推荐)
既然当前processAjaxError不需要执行异步操作,直接去掉async关键字,让它返回原始的Error实例即可:
function processAjaxError(jqXHR, textStatus, errorThrown) { let error = new Error("textStatus: "+textStatus+", errorThrown: "+errorThrown); return error; }
这样reject(error)传入的就是真正的Error实例,catch块就能直接捕获到它。
方案2:若processAjaxError需保留async(未来可能加异步逻辑)
如果以后processAjaxError需要执行异步操作(比如读取本地存储、调用其他接口等),那么在ajax的error回调里要先awaitprocessAjaxError,拿到真正的Error后再reject:
error: async function(jqXHR, textStatus, errorThrown) { let error = await processAjaxError(...arguments); reject(error); }
额外提示
你代码外层包裹的try/catch其实没有作用:$(document).ready()的回调是异步执行的,外层的同步try/catch无法捕获异步回调中的错误,所以可以直接去掉,只保留内部的try/catch就足够了。
备注:内容来源于stack exchange,提问作者Creech

