js中错误处理机制
1.基本知识
1. 错误对象
Error,SyntaxError,RangeError, ReferenceError,TypeError,URIError
上面的都是构造函数;
new 命令可以生成错误实例对象;可以传入描述作为参数,成为实例对象的message属性;
除了message属性,还有两个非标准属性(name, stack)stack是调用栈
var err = new Error("错误实例"); err.message; // "错误实例" err.name; //"Error" err.stack;//"Error: 错误实例 at <anonymous>:1:11"
2. throw语句
throw语句,如果不进行捕获(try...catch...),会中断当前script脚本中throw之后的所有代码执行。
<script> function test(){ console.log('1'); setTimeout(() => console.log('2')); //异步任务,下一轮执行,相当于最后执行 throw new Error("err"); //未捕获,这个script内的后面的代码都不执行 setTimeout(() => console.log('3')); // throw后 console.log('4'); // throw后 }; function a() { console.log('5') } test(); a(); //throw后 </script> <script> function b() { console.log('6') } b(); // 另一个脚本 </script> // 运行结果如下: 1 Error: err 6 2
如果在定时器中抛出异常,不会中断定时器之外的代码执行。定时器回调函数相当于自己一个“进程”。
示例: 将上面的未捕获异常放在setTimeout中
<script> function test(){ console.log('1'); setTimeout(() => console.log('2')); setTimeout(() => {throw new Error("err")}); //改为异步后,只影响本身 setTimeout(() => console.log('3')); console.log('4'); }; function a() { console.log('5') } test(); a(); </script> <script> function b() { console.log('6') } b(); </script> //运行结果如下 1 4 5 6 2 Uncaught Error: err 3
throw命令可以抛出任何类型的值;抛出什么,则捕获的就是什么!
try{ throw "error" } catch(err){ console.log(err); //"error" }
3.try...catch...finally..语句
使用try...catch...语句后,可以捕获错误,防止代码崩溃;
1)js中,程序执行遇到return, throw后,后面的语句不再执行;
try{ throw "this is a error"; console.log("after throw"); // 永远不会执行 } catch(error) { console.log(error); } // 运行结果
"this is a error"
2)浏览器中单独的try代码块中不能使用return;否则报错;而且catch无法捕获
try{ return "this is a error"; } catch { } // Uncaught SyntaxError: return not in a function
由上面可以知道,return语句必须用在function中。另外,yield语句也是必须在Generator函数中被调用。
如果想在try/catch/finally代码块中使用return语句,可以在外面包裹一层function。
3)catch语句
如果try代码块中代码本身不抛出异常,也没有手动抛出异常,程序永远不会进入catch代码块。
try { console.log("throw nothind"); } catch { // 参数可以省略 console.log("永远不会执行"); // try没有抛出错误,不会进入catch;永远不会被打印, }
如果try代码块中抛出异常,则代码进入catch代码块执行完后,继续原来的代码执行。
try { throw "error"; } catch { // 参数可以省略 console.log("catch") } console.log('after'); // 运行结果如下:
catch after
4)finally语句
finally语句不论是否抛出异常,都会执行。且try后者catch中的return语句取值会在finally之前取值。
var count = 1; function test() { try { console.log("try"); throw new Error("this is a error"); } catch(err) { console.log("catch error"); return count; } finally { console.log("finally") count+=1; } console.log("after"); //永远不会执行 } console.log(test());
// 运行结果如下 try catch error finally 1 //最后返回1,说明return在finally执行前先执行,但是最后才返回
如果在该代码块有return语句,会覆盖try,catch中的return语句
var count = 1; function test() { try { console.log("try"); throw new Error("this is a error"); } catch(err) { console.log("catch error"); return count; } finally { console.log("finally") count+=1; return count; } console.log("after"); //永远不会执行,因为前面有return语句 } console.log(test()); // 运行结果如下 try catch error finally 2 //执行的是finally语句中的return语句
如果在该代码块中有return语句,会覆盖catch中的throw语句;
var count = 1; function test() { try { throw new Error("this is a error"); } catch(err) { console.log("catch error"); throw err; // 不会执行;正常catch中遇到throw/return进入finally,等执行完finally代码块,返回这里抛出异常 } finally { return count; // return 后不会返回catch代码块;如果没有return,会返回catch模块继续抛出异常,然后被外部的try...catch捕获 } } try { test(); } catch(err) { console.log("catch test error"); // 不会执行 } // 运行结果如下:
catch error 1 //返回1
4. finally语句应用
示例: 操作文件时,打开文件写入,不管是否写入成功,都要关闭文件
// 伪代码如下 openFile(); try { writeFile() } catch(err) { console.log("写入失败"); } finally { closeFile(); // 总要执行 }
2. 实践应用
当使用接口请求服务器数据时,一般都要使用try...catch...方法,预防接口报错,程序崩溃!