前端异常捕获

398 阅读3分钟

错误机制

  JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例。
  Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error的6个派生对象。

  • SyntaxError对象:解析代码时发生的语法错误
  • ReferenceError对象:引用一个不存在的变量时发生的错误或将一个值分配给无法分配的对象
  • RangeError对象:一个值超出有效范围时发生的错误
  • TypeError对象:变量或参数不是预期类型时发生的错误
  • URIError对象:URI相关函数的参数不正确时抛出的错误
  • EvalError对象:eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。

捕获异常

try/catch

try/catch捕获“同步代码”中的“运行时异常”

<script>
    // 1.当前代码块将作为一个任务压入任务队列中,JavaScript线程会不断地从任务队列中提取任务执行;
    // 2.当任务执行过程中报异常,且异常没有捕获处理,则会一路沿着调用栈从顶到底抛出,最终终止当前任务的执行;
    // 3.JavaScript线程会继续从任务队列中提取下一个任务继续执行。
    function a() {
        throw Error("test")
    }
    function b(){a()}
    b()
    console.log("永远不会执行!")
</script>
<script>
// 下一个任务
    console.log("你有你抛异常,我照样执行!")
</script>

// 控制台打印
Uncaught Error: test
   at a (index.html:18)
   at b (index.html:20)
   at index.html:21
index.html:26 你有你抛异常,我照样执行!

使用try/catch,可以捕获异常继续执行下面的代码

<script>
    function a() {
        try {
            throw Error("test")
        } catch (e) {
            console.log(e)
        }
    }
    function b(){a()}
    b()
    console.log("永远不会执行!")
</script>
<script>
// 下一个任务
    console.log("你有你抛异常,我照样执行!")
</script>

// 控制台打印数据
Error: test
   at a (index.html:10)
   at b (index.html:15)
   at index.html:16
index.html:17 永远不会执行!
index.html:21 你有你抛异常,我照样执行!

window.onerror

window.onerror全局捕获异常,包括异步中的异常。

<script>
    window.onerror = function(message, source, lineno, colno, error){
        console.log(message)
    }
    setTimeout(function(){ throw Error("error!") }, 0)
</script>

// 控制台输出
Uncaught Error: error!
Uncaught Error: error!
   at  index.html:11

是不是window.onerror就可以捕获所有异常,答案是否定的。
1)Chrome中对于跨域脚本所报的异常,虽然onerror能够捕获,但统一报Script Error。若要得到正确的错误信息,则要配置跨域资源共享CORS才可以。
2)window.onerror实际上采用的事件冒泡的机制捕获异常,并且在冒泡(bubble)阶段时才触发,因此像网络请求异常这些不会冒泡的异常是无法捕获的。
3)Promise.reject产生的未被catch的异常,window.onerror也是无能为力。

promise异常捕获

<script>
	window.addEventListener("unhandledrejection", function(e){
	  cosole.log(e)
	  // 会阻止异常继续抛出,不让Uncaught(in promise) Error产生
	  e.preventDefault()
	})
</script>

捕获网络异常

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
<script>
    window.addEventListener("error", function(e){
        console.log(e) 
    }, true)
</script>
<div id="app">
    <img src="./1.png">
</div>
</body>
</html>

// 控制台打印

Event {
bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: null
defaultPrevented: false
eventPhase: 0
isTrusted: true
path: (6) [img, div#app, body, html, document, Window]
returnValue: true
srcElement: img
target: img
timeStamp: 29.179999997722916
type: "error"
proto: Event
}