JS-Error错误处理详解
错误处理
错误处理对于web应用程序开发至关重要,不能提前预测到可能发生的错误,不能提前采取恢复策略,可能导致较差的用户体验。
Error对象
任何没有通过try-catch处理的错误都会触发window对象的error事件。
//一般地,使用try-catch语句来捕获错误
try{
t;
}catch(ex){
console.log(ex.message);// message属性保存着错误信息
console.log(ex.name);// name属性保存错误类型
}
error事件
任何没有通过try-catch处理的错误都会触发window对象的error事件。
error事件可以接收三个参数:错误消息、错误所在的URL和行号。多数情况下,只有错误消息有用,因为URL只是给出了文档的位置,而行号所指的代码行既可能出自嵌入的JS代码,也可能出自外部的文件。
//DOM0级
window.onerror = function(message,url,line){
alert(message);
}
//DOM2级
window.addEventListener("error",function(message,url,line){
alert(message);
});
浏览器是否显示标准的错误消息,取决于onerror的返回值。如果返回值为false,则在控制台中显示错误消息;如果返回值为true,则不显示。
//控制台显示错误消息
window.onerror = function(message,url,line){
alert(message);
return false;
}
a;
//控制台不显示错误消息
window.onerror = function(message,url,line){
alert(message);
return true;
}
a;
这个事件处理程序是避免浏览器报告错误的最后一道防线。理想情况下,只要可能就不应该使用它。只要能够适当地使用try-catch语句,就不会有错误交给浏览器,也就不会触发error事件。
图像也支持error事件。只要图像的src特性中的URL不能返回可以被识别的图像格式,就会触发error事件。此时的error事件遵循DOM格式,会返回一个以图像为目标的event对象。
加载图像失败时会显示一个警告框。发生error事件时,图像下载过程已经结束,也就是不能再重新下载。
var image = new Image();
image.src = 'smilex.gif';
image.onerror = function(e){
console.log(e);
}
throw语句与抛出错误
throw语句用于抛出错误。抛出错误时,必须要给throw语句指定一个值,这个值是什么类型,没有要求。
[注意]抛出错误的过程是阻塞的,后续代码将不会执行。
throw 12345;
throw 'hello world';
throw true;
throw {name: 'javascript'};
throw new Error('something bad happened');
throw new SyntaxError('I don\'t like your syntax.');
throw new TypeError('what type of variable do you take me for?');
throw new RangeError('sorry,you just don\'t have the range.');
throw new EvalError('That doesn\'t evaluate.');
throw new URIError('URI, is that you?');
throw new ReferenceError('you didn\'t cite your references properly');
浏览器对待继承自Error的自定义错误类型,就像对待其他错误类型一样。如果要捕获自己抛出的错误并且把它与浏览器错误区别对待的话,创建自定义错误是很有用的。
function CustomError(message){
this.name = 'CustomError';
this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError('my message');
在遇到throw语句时,代码会立即停止执行。仅当有try-catch语句捕获到被抛出的值时,代码才会继续执行。
finally
虽然finally子句在try-catch语句中是可选的,但finally子句一经使用,其代码无论如何都会执行。只要代码中包含finally子句,则无论try或catch语句块中包含什么代码——甚至return语句,都不会阻止finally子句的执行。
//由于没有catch语句块,所以错误没有捕获。执行finally代码块以后,程序就中断在错误抛出的地方
function cleansUp() {
try {
throw new Error('出错了……');
console.log('此行不会执行');
} finally {
console.log('完成清理工作');
}
}
cleansUp();
// 完成清理工作
// Error: 出错了……
function f() {
try {
console.log(0);
throw "bug";
} catch(e) {
console.log(1);
return true; // 这句原本会延迟到finally代码块结束再执行
console.log(2); // 不会运行
} finally {
console.log(3);
return false; // 这句会覆盖掉前面那句return
console.log(4); // 不会运行
}
console.log(5); // 不会运行
}
var result = f();
块级作用域
try-catch语句的一个常见用途是创建块级作用域,其中声明的变量仅仅在catch内部有效。
try{
throw new Error();//抛出错误
}catch(e){
console.log(e);//Error(…)
}
console.log(e);//Uncaught ReferenceError: e is not defined
ES6引入了let关键字,为其声明的变量创建块级作用域。但是,在目前ES3和ES5的情况下,常常使用try-catch语句来实现类似的效果。