为什么 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)
}

因为 errorTestasync,它会 总是 return 一个承诺,它 永远不会 保证在下一条语句开始之前完成执行:它是异步errorTest returns,你退出 try 块,很可能在 errorTest 完全 运行 之前。因此,您的 catch 块将永远不会触发,因为 errorTest 中的任何内容都不会 同步 抛出异常。

承诺拒绝和异常是两种不同的失败渠道:承诺拒绝是异步的,异常是同步的。 async 会将同步异常 (throw) 转换为异步异常 (promise rejection),但除此之外,这是两个完全不同的系统。

(我之前写过异步函数不会立即开始 运行,这是我的错误:As on MDNasync 函数确实开始 运行立即但在第一个 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"))