首页 > 解决方案 > 为什么 try {} .. catch() 不能与 async/await 函数一起使用?

问题描述

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()andcatch()代替,它可以工作。

errorTest()
.then(val=> console.log(val))
.catch(err=> console.error("ERROR OCCURRED"))

这有效,但try {..} catch()无效。为什么?

我不断得到Uncaught (in promise) error.

标签: javascriptpromisetry-catch

解决方案


async function errorTest() { /* ... */ }

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

因为errorTestis async,它总是会返回一个 Promise 并且永远不会在你调用它的地方开始执行:它是异步的。返回,然后在运行其中的一行代码之前errorTest退出该块。因此,您的块永远不会触发,因为没有任何东西会同步抛出异常。tryerrorTestcatcherrorTest

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()错误的承诺链,所以在同一个函数中很少需要两种类型的错误。


正如 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"))

推荐阅读