错误类型数据

错误类型主要是运行过程中的前端报错,Javascript原生提供Error构造函数,所有抛出的错误都是它的实例。Error实例对象有以下属性

属性描述
message错误提示信息
name错误名称
stack错误的栈

image

异常情况

总的来说其实可以分很多种,轻则影响局部流程问题,严重的会影响页面崩溃甚至白屏

  • SyntaxError: 语法错误
  • TypeError: 类型错误
  • RangeError: 范围错误
  • ReferenceError: 引用错误
  • EvalError: eval错误
  • URIError: URL错误
  • AggregateError: 多个错误(实验中的功能
  • Failed to load resource: 资源加载错误

SyntaxError

当Javascript语言解析代码时,Javascript引擎发现了不符合语法规范的tokens或token顺序时抛出SyntaxError.

image

也可以手动抛出,语法如下

new SyntaxError([message[, fileName[, lineNumber]]])

image

TypeError

当传入函数的操作数参数的类型并非操作符或函数所预期的类型时,将抛出一个 TypeError 类型错误。

image

也可以手动抛出,语法如下

new TypeError([message[, fileName[, lineNumber]]])

image

RangeError

试图传递一个number参数给一个范围内不包含该number的函数时则会引发RangeError。当传递一个不合法的length值作为 Array 构造器的参数创建数组,或者传递错误值到数值计算方法(Number.toExponential(),Number.toFixed() ,Number.toPrecision()),会出现RangeError。.

image

也可以手动抛出,语法如下

new RangeError([message[, fileName[, lineNumber]]])

image

ReferenceError

当你尝试引用一个未被定义的变量时,将会抛出一个 ReferenceError

image

也可以手动抛出,语法如下

new ReferenceError([message[, fileName[, lineNumber]]])

image

EvalError

本对象代表了一个关于 eval 函数的错误.此异常不再会被JavaScript抛出,但是EvalError对象仍然保持兼容性.

image

也可以手动抛出,语法如下

new EvalError([message[, fileName[, lineNumber]]])

image

URIError

当向全局 URI 处理函数传递一个不合法的URI时,URIError 错误会被抛出。
image

也可以手动抛出,语法如下

new URIError([message[, fileName[, lineNumber]]])

image

AggregateError

一个AggregateError当需要由操作报告多个错误被抛出,例如通过Promise.any(),在传递给它的所有Promise拒绝。

image
也可以手动抛出,语法如下

new AggregateError(errors[, message])

image

Failed to load resource

以下标签加载资源出错 <img>, <input type="image">, <object>, <script>, <style>, <audio>, <video>

可以通过onerror或者全局监听error事件捕获,下文会提到

我们排除掉资源和语法等不可控的因素,从代码角度分析有哪些可以协助我们开发提高代码的健壮性.

Try-Catch

这种方式适用于你知道这段代码可能会出现异常或者当做代码出现异常的后备处理方式

try 语句测试代码块的错误。

catch 语句处理错误。

throw 语句创建自定义错误。

finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行。

1, 仅支持捕获同步异常

try {
  console.log(a)
} catch (error) {
  console.log('a is not defined')
} finally {
  console.log('always')
}

// a is not defined
// always

2, 不能用于捕获异步异常

try {
  setTimeout(() => {
    console.log(a)
  }, 1000)
} catch (e) {
  console.log('捕获到异常:', e);
}

// ReferenceError: a is not defined

3, 语法错误不在其可捕获范围

try {
  str = '
} catch (e) {
  console.log('捕获到异常:', e);
}

// SyntaxError: Invalid or unexpected token

Promise Catch

promise catch和try-catch的区别其实也跟回调函数和Promise的关系有渊源,前者也可用于捕获异步编程异常,后者仅支持同步流程

1, 同步异常捕获

new Promise(resolve => {
  resolve(a)
}).catch (err => {
  console.log('catch: ', err)
})

// catch:  ReferenceError: a is not defined

2, 异步异常捕获

new Promise(resolve => {
  setTimeout(() => {
    resolve(a)
  }, 1000)
}).catch(err => {
  console.log('catch: ', err)
})

// ReferenceError: a is not defined

3, 同样不能捕获语法错误

new Promise(resolve => {
  setTimeout(() => {
    str = '
    resolve()
  }, 1000)
}).catch(err => {
  console.log('catch: ', err)
})

// SyntaxError: Invalid or unexpected token

React && Vue 捕获API

依赖框架所提供的API,功能强大,但是也有版本兼容的问题

Vue errorHandler

Vue.config.errorHandler = function (err, vm, info) {
  // handle error
  // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
  // 只在 2.2.0+ 可用
}

指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例

从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃。

从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了。

从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理。

React componentDidCatch

这个没用过,贴上官网给你们自己看.

部分 UI 的 JavaScript 错误不应该导致整个应用崩溃,为了解决这个问题,React 16 引入了一个新的概念 —— 错误边界。

错误边界是一种 React 组件,这种组件可以捕获并打印发生在其子组件树任何位置的 JavaScript 错误,并且,它会渲染出备用 UI,而不是渲染那些崩溃了的子组件树。错误边界在渲染期间、生命周期方法和整个组件树的构造函数中捕获错误。

注意

错误边界无法捕获以下场景中产生的错误:

  • 事件处理
  • 异步代码(例如 setTimeoutrequestAnimationFrame 回调函数)
  • 服务端渲染
  • 它自身抛出来的错误(并非它的子组件)

如果一个 class 组件中定义了 static getDerivedStateFromError() 或 componentDidCatch() 这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界。当抛出错误后,请使用 static getDerivedStateFromError() 渲染备用 UI ,使用 componentDidCatch() 打印错误信息。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 你同样可以将错误日志上报给服务器
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // 你可以自定义降级后的 UI 并渲染
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

错误边界的工作方式类似于 JavaScript 的 catch {},不同的地方在于错误边界只针对 React 组件。只有 class 组件才可以成为错误边界组件。大多数情况下, 你只需要声明一次错误边界组件, 并在整个应用中使用它。

注意错误边界仅可以捕获其子组件的错误,它无法捕获其自身的错误。如果一个错误边界无法渲染错误信息,则错误会冒泡至最近的上层错误边界,这也类似于 JavaScript 中 catch {} 的工作机制。

window.onerror

相比于try-catch捕获可预知代码块,window.onerror用于全局捕获错误,

  • 当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。
  • 当一项资源(如<img>或<script>)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。这些error事件不会向上冒泡到window,不过(至少在Firefox中)能被单一的window.addEventListener捕获。
window.onerror = function(message, source, lineno, colno, error) { ... }

函数参数:

  • message:错误信息(字符串)。可用于HTML onerror=""处理程序中的event
  • source:发生错误的脚本URL(字符串)
  • lineno:发生错误的行号(数字)
  • colno:发生错误的列号(数字)
  • error:Error对象(对象)

若该函数返回true,则阻止执行默认事件处理函数。

1, 同步异常捕获

window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}

image

2, 异步异常捕获

window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}

new Promise(resolve => {
    setTimeout(() => {
        resolve(a)
    }, 1000)
}).catch(err => {
    console.log('catch: ', err)
})

image

3, 同样不能捕获语法错误

window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}
str = '

// Uncaught SyntaxError: Invalid or unexpected token

window.addEventListener

和window.onerror类似,只是捕获的参数不同,并且window.addEventListener还可以捕获到资源加载失败的异常

window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)

1, 同步异常捕获

window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)

a

image

2, 异步异常捕获

window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)

new Promise(resolve => {
    setTimeout(() => {
        resolve(a)
    }, 1000)
}).catch(err => {
    console.log('catch: ', err)
})

image

3, 同样不能捕获语法错误

window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)
str = '

// Uncaught SyntaxError: Invalid or unexpected token

4, 资源加载失败

<img src="https://www.abc.com/img.png" alt="" srcset="">

window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)

image


Afterward
621 声望62 粉丝

努力去做,对的坚持,静待结果