错误监控
异常捕获
运行时代码异常,会自动抛出错误,并中断后续代码的执行。
// 例子1
let x = y
console.log('aka') // 不会输出
// 例子2
JSON.parse('hello aka')
console.log('aka') // 不会输出
// 例子3
JSON.parse(undefined)
console.log('aka') // 不会输出
我们也可以通过throw
来手动抛出错误,
// 例子4
throw new Error('手动抛出的错误')
console.log('aka') // 不会输出
为了避免代码的异常不会影响后续代码的执行,我们应该使用try...catch
来捕获异常
// 例子1
try {
let x = y
} catch(err) {
console.log(err)
}
console.log('aka') // 输出
// 例子2
try {
JSON.parse('hello aka')
} catch(err) {
console.log(err)
}
console.log('aka') // 输出
// 例子4
try {
throw new Error('手动抛出的错误')
} catch(err) {
console.log(err)
}
console.log('aka')
以上重点在代码的错误,接下来是诸如文件读取、I/O操作类型的错误
fs.readFile('file', (err, data) => {
if (err) {
console.log(err) // 读取失败时,可输出错误信息以供开发者参考
}
console.log(data) // 读取失败时为undefined
})
即使文件读取失败,fs
模块也会帮我们捕获异常,因此后续代码的执行不受影响。
fetch('A')
.then(res => res.json())
.then(data => fetch('b', data))
.then(res => res.json())
.catch(err => console.log(err))
该代码中,无论是fetch
失败抛出错误,还是then
内部出现代码异常抛出错误,都会让promise
的状态变成rejected
,此时会把抛出的错误传给末端的catch
而最终形态的异常捕获就是try...catch
配合await
来捕获promise
内部的异常
try {
const data = await fetch()
} catch (e) {
console.log(e)
}
补充1:
let p = new Promise((resolve, reject) => {
throw new Error('error')
console.log(1) // 不输出
})
console.log(2) // 输出
简单来讲,promise
内部出现的异常会中断内部后续代码的执行,同时promise
的状态变成rejected
,等待着外部进行异常的捕获。通常我们会用.catch
或try...catch + await
来捕获该异常。
补充2:
try...catch
捕获捕获异步代码内部的错误,如:
try {
setTimeout(() => {
throw new Error('222')
})
} catch (e) {
console.log(2) // 不输出,因为没有捕获到异常
}
我们可以这样:
async function A() {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('222'))
})
})
} catch (e) {
console.log(e)
}
}
补充3:
也可以使用类似window.onerror
的方法来捕获一些资源加载的错误
window.onerror = function(errorMessage, scriptURI, lineNo, columnNo, error) {
console.log('errorMessage: ' + errorMessage); // 异常信息
console.log('scriptURI: ' + scriptURI); // 异常文件路径
console.log('lineNo: ' + lineNo); // 异常行号
console.log('columnNo: ' + columnNo); // 异常列号
console.log('error: ' + error); // 异常堆栈信息
}
内存泄漏
内存泄漏(memory leak),指的是不再使用的内存,却没有被即时的释放。
一个广为流传的错误观点:闭包会造成内存泄漏。
实际上这是十分错误的,之所以这种观点会流传至今,是因为早年的IE浏览器存在垃圾回收的BUG。内存泄漏指的是不再使用的变量没有被回收,可是闭包中的变量是我们需要用到的呀。每一个传播“闭包会造成内存泄漏”这种错误观念的同学都应该被打一顿...只要程序写错了才会造成内存泄漏。
常见内存泄漏
-
意外的全局变量
// 意外的声明了全局的变量,在页面关闭前a变量都不会被回收
(function A() {
a = '123'
})()