React组件抛出的错误,被捕获在不相关的promise的catch块中

Dmi*_*dov 6 javascript promise reactjs

这就是我遇到的问题.在React组件的渲染函数中,我有这个:

{first_name} {last_name}
Run Code Online (Sandbox Code Playgroud)

我用它替换了它:

{first_name.toUpperCase()} {last_name.toUpperCase()}
Run Code Online (Sandbox Code Playgroud)

我的应用程序无法再登录.我正在使用Axios与后端通信.Axios基于承诺.在我做出改变之后.它显然开始执行我的API调用thencatch块和块login.当我在catch块中打印响应时.

function login(data, success, error) {
  axios.post('/login',
    JSON.stringify(data),
    {
      baseURL: config.apiUrl,
      headers: { 'Content-Type': 'application/json; charset=utf-8' }
    })
  .then((response) => success(response.data))
  .catch((response) => {
    console.log(response)
    error(response.status)})
}
Run Code Online (Sandbox Code Playgroud)

我得到以下内容:

TypeError: Cannot read property 'toUpperCase' of undefined
Run Code Online (Sandbox Code Playgroud)

上面的组件(它是一个简单的组件,只是显示页面上的道具的东西)和API调用代码之间绝对没有任何关系.

这不是我第一次在我的应用中碰到这个问题.有没有人曾经碰到这样的事情?我知道我的组件中的变量是未定义的,这就是错误出现的原因.我的问题是它是如何在应用程序的另一端进入某个承诺的catch区块的.

Dmi*_*dov 4

事实证明,在 JavaScript 中,任何catch块都会捕获代码中任何地方抛出的任何错误。这是设计使然。

这是规格

throw语句引发用户定义的异常。当前函数的执行将停止(不会执行 throw 之后的语句),并且控制权将传递到catch调用堆栈中的第一个块。如果catch调用者函数之间不存在任何块,则程序将终止。

一种解决方法是对您引入的所有承诺使用处理程序,这将是console.log它没有预料到的任何事情,例如:

export function apiErrorHandler(handler) {
  return (error) => {
    if (error.stack) {
      throw error
    }
    if (error.status && error.data) {
      handler(error)
    } else {
      console.error('Unknown type of error thrown during service request or its handler:', error)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后将其插入 axios 服务:

export function serviceGetContacts(success, error) {
  axios.get(`/contacts`, cfg())
    .then((response) => success(response.data))
    .catch(apiErrorHandler(error))
}
Run Code Online (Sandbox Code Playgroud)