【问题标题】:Why is try {} .. catch() not working with async/await function?为什么 try {} .. catch() 不能与 async/await 函数一起使用?
【发布时间】:2022-01-21 21:30:19
【问题描述】:

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

【问题讨论】:

  • 您需要await errorTest() 才能在catch 块中获得错误。否则你需要附加一个.catch() 处理程序。
  • await errorTest() 不起作用。它给了我`等待仅在异步函数和模块的顶层主体中有效`错误。 catch() 处理程序有效,但我不明白为什么。我需要有人更详细地向我解释这一点。我以为使用async 会返回一个承诺,那么为什么外面的catch() 没有捕捉到它呢?
  • @Snirka then() 不返回承诺,而是解决承诺。您的其余评论根本没有解决我的问题。
  • 看,如果你执行一个返回promise的函数而你没有await,那么稍后会解决。任何处理也将在以后进行。所以one(); try { asyncFn() } catch() {} two(); 会调用one,然后asyncFn 然后 等待,然后调用two。在这段代码执行完 one(); 之后,无论 promise 发生什么,都将在未来发生。 try { await asyncFn() } catch() {} two();` 将在调用 two 之前等待来自 asyncFn 的承诺解决。如果asyncFn 导致拒绝,它将进入 catch 块。
  • try/catch 在处理承诺方面没有什么特别之处。带有被拒绝承诺的 await 将引发拒绝,从而触发 catch 块。

标签: javascript promise try-catch


【解决方案1】:

你需要等待errorTest

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)
}
}

【讨论】:

  • 你给我的例子和我的例子很不一样。我不想把 try and catch 放在函数里面。如果您要回答我的问题,请按照我提出的方式进行。不要改变问题。
  • 从您的代码中,您没有在 try catch 块中等待“erroTest()”,这就是您遇到“未捕获(承诺中)错误”的原因。并且 try catch 块必须在异步函数中,因为您必须等待“errorTest()”才能使其工作。
  • 所以,你的意思是说,catch() 没有捕获错误,因为没有捕获承诺本身,因为try {} 没有捕获承诺,而.then() 捕获?但是有没有一种错误?在这种情况下,错误是由断开的链接引起的,那么这是否像一个promise错误,要捕获它,必须先捕获promise?如果我犯了另一种错误怎么办,那它会起作用吗?在我的示例中,有没有办法在函数之外捕获承诺?
  • 是的。因为errorTest 是异步的,所以它会返回一个promise,并且只会在你等待它一个异步函数时执行。这就是为什么你有"Uncaught (in promise) error"。如果您在示例的 try catch 块中控制台 errorTest() 函数,您将拥有 "<pending>",这意味着您不会等待它。如果你故意犯错误,它会起作用。您可以通过将 try catch 块放在另一个异步函数中并调用该函数来捕获 errorTest() 函数之外的承诺,如我的示例所示。如果是错误,就会进入catch块
  • 您在第二个 try/catch 块中调用了 errorTest() 函数,尽管是在 console.log 中。所以错误被捕获是因为你在第一个catch()中抛出了错误,所以,当你这样做时,你在第二个try/catch块中调用了函数,它进入了第二个catch,但如果你没有' t 在第一个中抛出错误,或者 console.log 在第一个 catch 中抛出错误,它不会在第二个中被捕获 catch
【解决方案2】:
async function errorTest() { /* ... */ }

try { 
  errorTest()
}
catch(err) { 
  console.log("OUTSIDE ERROR!" + err)
}

因为errorTestasync,它会总是返回一个promise,并且永远不会在你调用它的地方开始执行:它是异步。 errorTest 返回,然后您退出 try 块,然后运行 ​​errorTest 中的一行代码。因此,您的 catch 块将永远不会触发,因为 errorTest 中的任何内容都不会同步抛出异常。

Promise 拒绝和异常是两种不同的失败渠道:Promise 拒绝是异步的,而异常是同步的。 async 会将同步异常 (throw) 转换为异步异常(承诺拒绝),否则这是两个完全不同的系统。

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 链接以检测错误,因此在同一个函数中很少需要两种类型的错误。


在 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"))

【讨论】:

  • 所以,问题是try{} 没有捕获承诺,因此没有将承诺错误传递给catch(),或者因为try{} 是未同步,JS 执行它但不等待返回值,而是立即执行catch(),导致catch() 没有收到try{} 抛出的错误?我尝试了相同的示例,但使用原始值 const result = a - c; return resultc 未定义,并且它有效,catch() 捕获了错误。那么,第一个解释正确吗?
  • 另外,很抱歉,我不太理解你的例子。在您的第一个示例中,您正在返回一个新的承诺,所以.. 如果里面有错误,怎么会不会抛出任何东西?在您的第二个示例中,您只是定义了一个新的错误。这与问题有什么关系?您非常强调代码的同步与异步方面,但我已经建立了一个捕获承诺与不捕获,解决与不解决的心理形象......并且对异步与同步的强调并没有真正引起共鸣我很喜欢。我希望这是有道理的。
  • 我的整个目的是有两个catch(),以证明如果出现错误,最接近产生错误的函数的catch() 将捕获它,但我很难提出有这样的情况。
猜你喜欢
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
  • 2018-10-17
  • 2019-03-14
  • 2016-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多