为什么 try {} .. catch() 不能使用 async/await 函数?
Why is try {} .. catch() not working with async/await function?
const errorTest = async() => {
const result = await $.get("http://dataa.fixer.io/api/latest?access_key=9790286e305d82fbde77cc1948cf847c&format=1");
return result;
}
try {
errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
URL 故意不正确抛出错误,但外部 catch()
它没有捕获它。为什么?
如果我改用 then()
和 catch()
,就可以了。
errorTest()
.then(val=> console.log(val))
.catch(err=> console.error("ERROR OCCURRED"))
这有效,但 try {..} catch()
无效。为什么?
我一直收到 Uncaught (in promise) error
。
您需要等待错误测试
const callFunction=async()=>{
try{
const result = await errorTest()
}catch(err){
console.log(err)
}
}
callFunction ()
请注意,await errorTest() 函数也必须位于异步函数中。这就是为什么我把它放在 callFunction ()
另一种选择
const errorTest = async() => {
try{
const result = await $.get("http://dataa.fixer.io/api/latest?access_key=9790286e305d82fbde77cc1948cf847c&format=1");
console.log(result)
}catch(err){
console.log(err)
}
}
async function errorTest() { /* ... */ }
try {
errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
因为 errorTest
是 async
,它会 总是 return 一个承诺,它 永远不会 保证在下一条语句开始之前完成执行:它是异步。 errorTest
returns,你退出 try
块,很可能在 errorTest
完全 运行 之前。因此,您的 catch
块将永远不会触发,因为 errorTest
中的任何内容都不会 同步 抛出异常。
承诺拒绝和异常是两种不同的失败渠道:承诺拒绝是异步的,异常是同步的。 async
会将同步异常 (throw
) 转换为异步异常 (promise rejection),但除此之外,这是两个完全不同的系统。
(我之前写过异步函数不会立即开始 运行,这是我的错误:As on MDN,async
函数确实开始 运行立即但在第一个 await
点暂停,但他们抛出的错误将转换为承诺拒绝,即使它们确实立即发生。)
function errorTest() {
return new Promise(/* ... */); // nothing throws!
}
function errorTestSynchronous() {
throw new Error(/* ... */); // always throws synchronously
}
function errorTestMixed() {
// throws synchronously 50% of the time, rejects 50% of the time,
// and annoys developers 100% of the time
if (Math.random() < 0.5) throw new Error();
return new Promise((resolve, reject) => { reject(); });
}
在这里你可以看到各种形式的投掷。第一个 errorTest
与您的完全相同:async
函数的工作方式就好像您已将代码重构为新的 Promise。第二个 errorTestSynchronous
同步抛出:它会触发您的 catch
块,但因为它是同步的,所以您失去了对其他异步操作(例如 $.get
调用)作出反应的机会。最后,errorTestMixed
可以两种方式失败:它可以抛出,也可以拒绝承诺。
由于所有的同步错误都可以变成异步的,而且所有的异步代码都应该有 .catch()
错误的 promise 链,所以在同一个函数中很少需要两种类型的错误,通常更好的风格是始终对 async
或 Promise-returning 函数使用异步错误——即使这些错误来自 async
函数中的 throw
语句。
如 Ayotunde Ajayi 的回答,您可以通过使用 await
将异步错误转换为同步出现来解决此问题,因为 await
会将 Promise 失败解包回抛出的异常:
// within an async function
try {
await errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
但在幕后,它会完全按照您在问题中的建议显示:
errorTest()
.then(val=> console.log(val))
.catch(err=> console.error("ERROR OCCURRED"))
const errorTest = async() => {
const result = await $.get("http://dataa.fixer.io/api/latest?access_key=9790286e305d82fbde77cc1948cf847c&format=1");
return result;
}
try {
errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
URL 故意不正确抛出错误,但外部 catch()
它没有捕获它。为什么?
如果我改用 then()
和 catch()
,就可以了。
errorTest()
.then(val=> console.log(val))
.catch(err=> console.error("ERROR OCCURRED"))
这有效,但 try {..} catch()
无效。为什么?
我一直收到 Uncaught (in promise) error
。
您需要等待错误测试
const callFunction=async()=>{
try{
const result = await errorTest()
}catch(err){
console.log(err)
}
}
callFunction ()
请注意,await errorTest() 函数也必须位于异步函数中。这就是为什么我把它放在 callFunction ()
另一种选择
const errorTest = async() => {
try{
const result = await $.get("http://dataa.fixer.io/api/latest?access_key=9790286e305d82fbde77cc1948cf847c&format=1");
console.log(result)
}catch(err){
console.log(err)
}
}
async function errorTest() { /* ... */ }
try {
errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
因为 errorTest
是 async
,它会 总是 return 一个承诺,它 永远不会 保证在下一条语句开始之前完成执行:它是异步。 errorTest
returns,你退出 try
块,很可能在 errorTest
完全 运行 之前。因此,您的 catch
块将永远不会触发,因为 errorTest
中的任何内容都不会 同步 抛出异常。
承诺拒绝和异常是两种不同的失败渠道:承诺拒绝是异步的,异常是同步的。 async
会将同步异常 (throw
) 转换为异步异常 (promise rejection),但除此之外,这是两个完全不同的系统。
(我之前写过异步函数不会立即开始 运行,这是我的错误:As on MDN,async
函数确实开始 运行立即但在第一个 await
点暂停,但他们抛出的错误将转换为承诺拒绝,即使它们确实立即发生。)
function errorTest() {
return new Promise(/* ... */); // nothing throws!
}
function errorTestSynchronous() {
throw new Error(/* ... */); // always throws synchronously
}
function errorTestMixed() {
// throws synchronously 50% of the time, rejects 50% of the time,
// and annoys developers 100% of the time
if (Math.random() < 0.5) throw new Error();
return new Promise((resolve, reject) => { reject(); });
}
在这里你可以看到各种形式的投掷。第一个 errorTest
与您的完全相同:async
函数的工作方式就好像您已将代码重构为新的 Promise。第二个 errorTestSynchronous
同步抛出:它会触发您的 catch
块,但因为它是同步的,所以您失去了对其他异步操作(例如 $.get
调用)作出反应的机会。最后,errorTestMixed
可以两种方式失败:它可以抛出,也可以拒绝承诺。
由于所有的同步错误都可以变成异步的,而且所有的异步代码都应该有 .catch()
错误的 promise 链,所以在同一个函数中很少需要两种类型的错误,通常更好的风格是始终对 async
或 Promise-returning 函数使用异步错误——即使这些错误来自 async
函数中的 throw
语句。
如 Ayotunde Ajayi 的回答,您可以通过使用 await
将异步错误转换为同步出现来解决此问题,因为 await
会将 Promise 失败解包回抛出的异常:
// within an async function
try {
await errorTest()
}
catch(err) {
console.log("OUTSIDE ERROR!" + err)
}
但在幕后,它会完全按照您在问题中的建议显示:
errorTest()
.then(val=> console.log(val))
.catch(err=> console.error("ERROR OCCURRED"))