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

An error thrown by a React component, being caught in an unrelated promise's catch block

本文关键字:不相关 promise 块中 catch 组件 React 错误      更新时间:2023-09-26

这是我碰到的。在 React 组件的渲染函数中的某个地方,我有这个:

{first_name} {last_name}

我用这个替换了它:

{first_name.toUpperCase()} {last_name.toUpperCase()}

我的应用程序无法再登录。我正在使用 Axios 与后端通信。Axios是基于承诺的。在我进行了上述更改之后。它显然开始执行我的login API调用的thencatch块。当我在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)})
}

我得到以下信息:

TypeError: Cannot read property 'toUpperCase' of undefined

上面的组件(它是一个愚蠢的组件,只是在页面上显示来自 props 的内容)和 API 调用代码之间绝对没有关系。

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

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

这是规格:

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

然后将其插入 axios 服务:

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

如果尚未定义名字或姓氏,则更改将引发 TypeError。 在登录过程完成之前,这非常容易。

请尝试改用以下内容:

{first_name && first_name.toUpperCase()} {last_name && last_name.toUpperCase()}