- 发布于
js异常处理
- Authors
- Name
- 田中原
前端异常处理简介
错误类型
每当运行发生错误时,会抛出一个错误对象。 每种错误都有对应的错误类型,而当错误发生的时候就会抛出相应的错误对象。
- Error:错误的基础对象,其他错误都继承自该类型
- EvalError:Eval函数没有正确执行时的错误
- RangeError:当一个值不在有效范围之内时的错误
- ReferenceError:引用一个未被定义的变量时的错误
- SyntaxError:解析代码时语法不正确的错误
- TypeError:值的类型非预期类型时的错误
- URIError:使用全局URI处理函数时参数不正确的错误
- AggregateError:当多个错误需要包装在一个错误中时,表示一个错误(实验中的功能)
Error
错误的基础对象,其他错误都继承自该类型
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
const error1 = new Error('错误error1')
console.log(error1.message) // 错误error1
EvalError
Eval函数没有正确执行时的错误。此异常不再会被抛出,但是EvalError对象仍然保持兼容性
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
RangeError
当一个值不在有效范围之内时的错误
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
// 数组长度为负数
new Array(-1) // Uncaught RangeError: Invalid array length
// 使用Number对象的方法时,传入的参数超出了范围
// 参数超出范围
;(66.6).toExponential(101) // Uncaught RangeError: toExponential() argument must be between 0 and 100
;(66.6).toFixed(101) // Uncaught RangeError: toFixed() digits argument must be between 0 and 100
;(66.6).toPrecision(101) // Uncaught RangeError: toPrecision() argument must be between 1 and 100
// 手动抛出错误
new RangeError('RangeError') // RangeError: RangeError
ReferenceError
引用一个未被定义的变量时的错误
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
let a = b // Uncaught ReferenceError: b is not defined
// 把一个值分配给无法分配的对象
function abc() {}
// 对函数运行结果进行赋值
abc() = 1 // Uncaught ReferenceError: Invalid left-hand side in assignment
// 手动抛出错误
new ReferenceError('ReferenceError') // ReferenceError: ReferenceError
SyntaxError
解析代码时语法不正确的错误
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
// 变量声明时错误
let 777 // Uncaught SyntaxError: Unexpected number
// 调用函数时缺少括号
console.log(123 // Uncaught SyntaxError: missing ) after argument list
// 手动抛出错误
new SyntaxError('SyntaxError') // SyntaxError: SyntaxError
TypeError
值的类型非预期类型时的错误
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
// 变量声明时错误
let a = 123
a.shift() // Uncaught TypeError: a.shift is not a function
// 手动抛出错误
new TypeError('TypeError') // TypeError: TypeError
URIError
使用全局URI处理函数时参数不正确的错误
- message:可选,错误描述信息
- fileName:可选,调用Error构造函数代码所在的文件名字(这个参数不是标准参数)
- lineNumber:可选,调用Error构造函数代码所在的文件行号(这个参数不是标准参数)
decodeURI('%') // Uncaught URIError: URI malformed
// 手动抛出错误
new URIError('URIError') // URIError: URIError
AggregateError
当多个错误需要包装在一个错误中时,表示一个错误(实验中的功能)
- errors:可选,错误对象数组
- message:可选,错误的提示信息
let p1 = Promise.reject(new Error('p1 error'))
let p2 = Promise.reject(new Error('p2 error'))
let p3 = Promise.reject(new Error('p3 error'))
Promise.any([p1, p2, p3]).catch((e) => {
console.log(e.message) // All promises were rejected
console.log(e.name) // AggregateError
console.log(e.errors[0].message) // p1 error
console.log(e.errors[1].message) // p2 error
console.log(e.errors[2].message) // p3 error
})
// 手动抛出错误
try {
throw new AggregateError(
[new Error('AggregateError1'), new Error('AggregateError2')],
'One AggregateError'
)
} catch (e) {
console.log(e.message) // One AggregateError
console.log(e.name) // AggregateError
console.log(e.errors[0].message) // AggregateError1
console.log(e.errors[1].message) // AggregateError2
}
异常捕获
try-catch
当不确定某段代码是否会出错时,可以将这段代码放入try代码块中,报错时在catch中进行处理
捕获同步异常
try {
throw new Error('error1')
} catch (e) {
console.log(`捕获到异常信息:${e}`)
}
// 捕获到异常信息:Error: error1
不能用于捕获异步异常
try {
setTimeout(() => {
throw new Error('error1')
}, 1000)
} catch (e) {
console.log(`捕获到异常信息:${e}`)
}
// Uncaught Error: error1
不能用于捕获JavaScript语法错误,手动抛出的语法错误可以捕获
try {
let a = ;
} catch (e) {
console.log(`捕获到异常信息:${e}`)
}
// Uncaught SyntaxError: Unexpected token ';'
try {
throw new SyntaxError('error1')
} catch (e) {
console.log(`捕获到异常信息:${e}`)
}
// 捕获到异常信息:SyntaxError: error1
Promise catch
Promise中的异常不会被try-catch和window.onerror捕获
捕获同步异常
new Promise((resolve, reject) => {
throw new Error('error1')
}).catch((e) => {
console.log(`捕获到异常信息:${e}`)
})
// 捕获到异常信息:Error: error1
不能用于捕获异步异常
new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error('error1')
}, 1000)
}).catch((e) => {
console.log(`捕获到异常信息:${e}`)
})
// Uncaught Error: error1
不能用于捕获JavaScript语法错误,手动抛出的语法错误可以捕获
new Promise((resolve, reject) => {
let a = ;
resolve(a)
}).catch(e => {
console.log(`捕获到异常信息:${e}`)
})
// Uncaught SyntaxError: Unexpected token ';'
new Promise((resolve, reject) => {
throw new SyntaxError('error1')
resolve()
}).catch(e => {
console.log(`捕获到异常信息:${e}`)
})
// 捕获到异常信息:SyntaxError: error1
Vue errorHandler
指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}
- 从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃。
- 从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了。
- 从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理。
window.onerror
当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。若该函数返回true,则阻止执行默认事件处理函数,控制台不会显示默认的报错信息。
- message:错误信息(字符串)
- source:发生错误的脚本URL(字符串)
- lineno:发生错误的行号(数字)
- colno:发生错误的列号(数字)
- error:Error对象(对象)
捕获同步异常
window.onerror = function (message, source, lineno, colno, error) {
console.log('捕获到异常信息:', { message, source, lineno, colno, error })
}
throw new Error('error1')
/*
捕获到异常信息:
{
message: "Uncaught Error: error1",
source: "file:///D:/1.html",
lineno: 15,
colno: 11,
error: Error: error1
}
*/
// Uncaught Error: error1
捕获异步异常
window.onerror = function (message, source, lineno, colno, error) {
console.log('window.onerror 捕获到异常信息:', { message, source, lineno, colno, error })
}
new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error('error1')
}, 1000)
resolve()
}).catch((e) => {
console.log(`Promise catch 捕获到异常信息:${e}`)
})
/*
window.onerror 捕获到异常信息:
{
message: "Uncaught Error: error1",
source: "file:///D:/1.html",
lineno: 17,
colno: 15,
error: Error: error1
}
*/
// Uncaught Error: error1
不能用于捕获JavaScript语法错误,手动抛出的语法错误可以捕获
window.onerror = function (message, source, lineno, colno, error) {
console.log('window.onerror 捕获到异常信息:', {message, source, lineno, colno, error})
}
let a = ;
// Uncaught SyntaxError: Unexpected token ';'
throw new SyntaxError('error1')
/*
window.onerror 捕获到异常信息:
{
message: "Uncaught SyntaxError: error1",
source: "file:///D:/1.html",
lineno: 16,
colno: 7,
error: SyntaxError: error1
}
*/
// Uncaught SyntaxError: error1
window.addEventListener('error', error => )
与window.onerror功能类型,事件回调函数的参数不同,不能阻止执行默认事件处理函数,控制台会显示默认的报错信息。
- type:事件类型(字符串)
- listener:监听的事件类型触发时处理事件的函数(函数)
- useCapture:可选,默认值为false,在冒泡阶段处理事件;为true时,在捕获阶段处理事件(布尔值)
捕获同步异常
window.addEventListener(
'error',
(error) => {
console.log(`window.addEventListener 捕获到异常信息:${error}`)
},
true
)
throw new Error('error1')
// window.addEventListener 捕获到异常信息:[object ErrorEvent]
// Uncaught Error: error1
捕获异步异常
window.addEventListener(
'error',
(error) => {
console.log(`window.addEventListener 捕获到异常信息:${error}`)
},
true
)
new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error('error1')
}, 1000)
resolve()
}).catch((e) => {
console.log(`Promise catch 捕获到异常信息:${e}`)
})
// window.addEventListener 捕获到异常信息:[object ErrorEvent]
// Uncaught Error: error1
不能用于捕获JavaScript语法错误,手动抛出的语法错误可以捕获
window.addEventListener('error', error => {
console.log(`window.addEventListener 捕获到异常信息:${error}`)
}, true)
let a = ;
// Uncaught SyntaxError: Unexpected token ';'
throw new SyntaxError('error1')
// window.addEventListener 捕获到异常信息:[object ErrorEvent]
// Uncaught SyntaxError: error1
资源加载异常
window.addEventListener('error', error => )
<script>
window.addEventListener(
'error',
(error) => {
console.log(`window.addEventListener 捕获到异常信息:${error}`)
},
true
)
</script>
<link rel="stylesheet" href="http://localhost/test.css" />
<img src="http://localhost/test.png" />
<script src="http://localhost/test.js"></script>
<!-- GET http://localhost/test.css net::ERR_CONNECTION_REFUSED -->
<!-- window.addEventListener 捕获到异常信息:[object Event] -->
<!-- GET http://localhost/test.js net::ERR_CONNECTION_REFUSED -->
<!-- window.addEventListener 捕获到异常信息:[object Event] -->
<!-- GET http://localhost/test.png net::ERR_CONNECTION_REFUSED -->
<!-- window.addEventListener 捕获到异常信息:[object Event] -->