【问题标题】:An error thrown by a React component, being caught in an unrelated promise's catch blockReact 组件抛出的错误,被不相关的 Promise 的 catch 块捕获
【发布时间】:2016-05-22 13:31:17
【问题描述】:

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

{first_name} {last_name}

我用这个替换它:

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

我的应用程序无法再登录。我正在使用 Axios 与后端对话。 Axios 是基于承诺的。在我进行上述更改之后。它显然开始执行我的login API 调用的then 和catch 块。当我在 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 调用代码之间绝对没有任何关系。

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

【问题讨论】:

    标签: javascript reactjs promise


    【解决方案1】:

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

    这是spec:

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

    然后将其插入 axios 服务:

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

    【讨论】:

    • 鉴于这是设计使然,您能否提供有关为什么这是所需行为的见解?
    • 这是 JavaScript。通过设计!=所需的行为。 ))
    • 为什么 Axios 调用是该组件渲染的调用堆栈的一部分?我遇到了与 errbody else here 相同的问题
    • @LeoLei 它不是调用堆栈的一部分。请参阅答案中的规范链接。
    【解决方案2】:

    如果尚未定义名字或姓氏,您的更改将引发 TypeError。在登录过程完成之前这很可能。

    尝试改用这个:

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

    【讨论】:

    • 我对问题进行了澄清,请参阅最后一段。
    猜你喜欢
    • 2020-11-20
    • 2023-03-28
    • 2014-07-26
    • 2012-06-06
    • 2017-06-29
    • 2017-06-20
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    相关资源
    最近更新 更多