如何检测是否在Promise的捕获块中

时间:2019-03-28 14:29:56

标签: javascript error-handling promise callback

我已经编写了一些荒谬的简单错误处理代码,这些代码可完美地用于同步操作。我不得不修改throwError函数以实现我对异步操作的期望,但是现在它不能像我期望的那样在同步操作下工作。如何检测是否在Promise的catch块中调用了该函数以更改行为?

以下是适用于同步操作的代码:

const errorHandler = () => console.log('Woot, handled error')
const throwError = (error) => {
  throw error
}

try {
  throwError(new Error('Blah blah'))
  console.log('This should not be reached')
} catch(error) {
  errorHandler(error)
}

以下是最适合异步操作的代码:

const errorHandler = () => console.log('Blah blah')
const throwError = (error) => {
  errorHandler(error)
}

const loadStuff = () => new Promise((_, reject) => {
  console.log('Loading stuff')
  setTimeout(() => reject(new Error('Oh no, an error!')), 1000)
})

try {
  loadStuff().catch(throwError)
} catch(error) {
  errorHandler(error)
}

但是,如果将异步throwError代码放入同步代码中,则会执行第二个console.log。如果您将同步throwError放在异步代码中,则会产生未处理的承诺拒绝错误。

仅使用一个throwError函数,我如何知道它是在捕获Promise还是被手动调用以在直接调用errorHandlerthrow错误之间切换?假设只有throwError和最后一个catch子句可以访问errorHandler

由于某些原因很难写出这个问题,并且可能措辞太怪异了,我希望您能进行一些澄清的编辑。

1 个答案:

答案 0 :(得分:0)

问题在于:

  

但是,如果将异步throwError代码放入同步代码中,则会执行第二个console.log。如果将sync throwError放入异步代码中,则会产生未处理的承诺拒绝错误。

也许应该事先弄清楚一些事情,您编写的两个函数 throwError 做的事情完全不同,一个函数收到错误并抛出错误,而另一个函数仅记录'等等等等。

另一方面,代码中

const errorHandler = () => console.log('Blah blah')
const throwError = (error) => {
  errorHandler(error)
}

const loadStuff = () => new Promise((_, reject) => {
  console.log('Loading stuff')
  setTimeout(() => reject(new Error('Oh no, an error!')), 1000)
})

try {
  loadStuff().catch(throwError)
} catch(error) {
  errorHandler(error)
}

如果我们将throwError函数更改为与第一个函数相同,那么代码将如下所示:

const errorHandler = () => console.log('Blah blah')
const throwError = (error) => {
   throw error
}

const loadStuff = () => new Promise((_, reject) => {
  console.log('Loading stuff')
  setTimeout(() => reject(new Error('Oh no, an error!')), 1000)
})

try {
  loadStuff().catch(throwError)
} catch(error) {
  errorHandler(error)
}

这里发生的事情是,一旦loadStuff被拒绝,则执行throwError函数,从而引发错误,但不会在try / catch语句中将其捕获为 try 不要抛出错误,因为loadStuff只是返回一个承诺, loadStuff的捕获中发生的情况与try / catch的捕获无关,因为它具有不同的scope 。实际上,如果这样捕获,则两个捕获可以同时执行:

const errorHandler = () => console.log('Blah blah')
const throwError = (error) => {
   console.log('another catch')
   throw error
}

const loadStuff = () => new Promise((_, reject) => {
  console.log('Loading stuff')
  setTimeout(() => reject(new Error('Oh no, an error!')), 1000)
})

try {
  loadStuff().catch(throwError)
  throw new Error('my Error')
} catch(error) {
  errorHandler(error)
}

这样说并假设,每次抛出错误时,您都希望以相同的方式来处理它,可能的解决方案是将其编写为:

const errorHandler = () => console.log('Blah blah')

const loadStuff = () => new Promise((_, reject) => {
  console.log('Loading stuff')
  setTimeout(() => reject(new Error('Oh no, an error!')), 1000)
})

try {
  loadStuff().catch(errorHandler)
} catch(error) {
  errorHandler(error)
}