【问题标题】:How to catch a callback error with a try catch?如何使用 try catch 捕获回调错误?
【发布时间】:2019-01-19 18:50:05
【问题描述】:

我有一个获取文件内容的异步函数,如下所示:

async function getFile (name) {
  return new Promise(function (resolve, reject) {
    fs.readFile(`./dir/${name}.txt`, 'utf8', function (error, file) {
      if (error) reject(error)
      else resolve(file)
    })
  })
}

我将该函数调用到控制台日志中

getFile('name').then( console.log )

如果我犯了错误,比如文件名拼写错误,我会收到这个方便的错误:

(node:17246) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async 
function without a catch block, or by rejecting a promise which was not 
handled with .catch(). (rejection id: 1)

我可以通过这样做来解决它:

getFile('name').then( console.log ).catch( console.log ) 但是有没有办法处理回调中的错误?也许是一次尝试?我该怎么做?

【问题讨论】:

  • 干脆别打电话reject?弄清楚error要做什么,然后把它放在readFile里面?
  • “处理回调中的错误”是什么意思?更具体地说,当出现错误时,您希望发生什么:让名为 getFile 的代码处理它还是返回其他内容?
  • @kirbuchi 理想情况下,该函数没有副作用,例如记录错误。它会做一件事,一件事只返回一个文件或返回一个错误。
  • @Costa 这正是它的作用,返回错误。当您不处理它时,您会收到一个有用的未处理拒绝警告。如果您想处理它但不记录它,请使用.catch(err => { /* ignore */ }) 而不是.catch(console.log)。 (当然是等效的async/await 代码)。

标签: javascript async-await try-catch


【解决方案1】:

您仍然需要捕获 rejected 的错误。

我认为这是您调用 getFile 函数的地方 - 需要将其包装在 try/catch 块中

try {
  const result = await getFile('name')
} catch(e) {
  ... You should see rejected errors here
}

或者,我认为这适用于您的示例:

await getFile('name').then( console.log ).catch(e => {...})

在 Chrome DevTools 控制台中对此进行测试:

async function test () {
  return new Promise(function(resolve, reject) {
    throw 'this is an error';
  })
}

并通过以下方式调用它:

await test().catch(e => alert(e))

表明这确实有效!

【讨论】:

  • 用 try catch 替换 if (error)... else... 没有用。现在我的错误案例只是未定义。发生这种情况是因为它首先尝试解析,但文件为空。
  • @Costa - 查看您的代码getFile('name').then( console.log ),我认为您应该“等待”结果。即await getFile('name').then( console.log )。否则我用一个工作示例调整了答案,它肯定能按预期工作
【解决方案2】:

如果我理解正确,您希望您的函数能够解决,无论您是否有错误。如果是这样,无论哪种情况,您都可以resolve

async function getFile (name) {
  return new Promise(function (resolve, reject) {
    fs.readFile(`./dir/${name}.txt`, 'utf8', function (error, file) {
      if (error) resolve(error)
      else resolve(file)
    })
  })
}

然后您需要处理外部错误,例如

getFile('name')
  .then(getFileOutput => {
    if (getFileOutput instanceof Error) {
      // we got an error
    } else {
      // we got a file
    }
  })

const getFileOutput = await getFile('name');
if (getFileOutput instanceof Error) {
  // we got an error
} else {
  // we got a file
}

这就是你要找的吗?

【讨论】:

  • 嗯....我现在意识到我可能不想要那个。悲伤的脸。如何防止我的功能产生副作用。我想我应该像你说的那样在外面处理错误,但也许拒绝是明智的,然后在外面处理拒绝。
  • Zach 回答的第一个 sn-p 是我看到人们正常做的/我会做的。但这取决于你:)
  • 在这种情况下,您可以将这一行:if (error) resolve(error) 替换为if (error) throw error,然后您将得到与下面我的答案等效的内容,因为您可以捕获函数调用的结果 (感谢@Bergi 的编辑,我明白了这一点)
猜你喜欢
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 2021-01-26
  • 2016-05-29
  • 2021-10-08
  • 2013-07-18
  • 1970-01-01
相关资源
最近更新 更多