为什么try-catch块无法捕获Promise异常?异步函数错误处理疑问
嘿,这个问题其实挺常见的,很多刚接触async/await和Promise的同学都会踩这个坑~我来给你捋清楚原因和解决办法。
首先你要明白:async函数执行后返回的是一个Promise对象,它内部抛出的错误并不会同步触发,而是会把这个错误作为Promise的reject结果。
你现在的写法是:
var test = async function(){ throw new Error('Just another error') } try { test().then() } catch(err){ alert('error: ' + err.toString()) }
这里的try..catch只能捕获同步执行过程中的错误——也就是调用test()或者.then()这一步有没有同步报错,但test()内部抛出的错误是被包装到Promise的reject里的,属于异步错误,try..catch根本“看不到”这个异步发生的错误,所以自然不会触发alert,而是让错误变成了未捕获的Promise错误(就是控制台里的“Uncaught (in promise) Error”)。
那该怎么正确捕获这个错误呢?有两种常用的方法:
方法一:用await结合try..catch(推荐)
既然async函数返回Promise,那我们可以用await来等待这个Promise完成,await会把Promise的reject结果转化为同步的抛出错误,这样try..catch就能捕获到了:
var test = async function(){ throw new Error('Just another error') } // 要在async函数里用await,所以我们包裹一层 async function runTest() { try { await test(); // 等待Promise完成,错误会被同步抛出 } catch(err) { alert('error: ' + err.toString()) } } runTest();
方法二:给Promise链添加.catch()
Promise本身提供了.catch()方法来捕获链中的reject错误,你可以直接在.then()后面加上.catch():
var test = async function(){ throw new Error('Just another error') } test() .then() // 这里可以写正常逻辑的处理 .catch(err => { alert('error: ' + err.toString()) });
这样Promise链里的任何reject错误都会被最后的.catch()捕获到。
总结一下核心点:try..catch只能处理同步代码的错误,而async函数内部的错误是异步的Promise reject,必须要么用await把它转为同步错误捕获,要么用Promise自身的.catch()方法来处理。
内容的提问来源于stack exchange,提问作者timrosskamp

