ry/catch/finally语句用于处理代码中可能出现的错误信息。
错误可能是语法错误,通常是程序员造成的编码错误或错别字。也 可能是拼写错误或语言中缺少的功能(可能由于浏览器差异)。
try:语句允许我们定义在执行时进行错误测试的代码块。
catch: 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
finally :语句在 try 和 catch 之后无论有无异常都会执行。
注意: catch 和 finally 语句都是可选的,但你在使用 try 语句时必须至少使用一个。
提示: 当错误发生时, JavaScript 会停止执行,并生成一个错误信息。使用 throw 语句 或 console.error() 来创建自定义消息(抛出异常)。如果你将 throw 和 try 、 catch一起使用,就可以控制程序输出的错误信息。
try或catch里有return时,先执行finally,再执行return;且finally中不能修改try和catch中变量的值
try {
//运行(出错)
throw '异常信息';
} catch (error) {
//捕获
} finally {
//最后一定执行。一般用于释放资源,如数据库连接、文件流等
}
**场景一:**try/catch/throw进行流程(if)控制,抛出自定义的异常信息。
function getStringToArray(str){
try {
if(str === undefined || str === null){
//抛异常后,停止向下执行了,直接运行catch代码
throw "出错了!这个不是字符串,undefined / null是没任何属性的";//throw语句:创建自定义错误, 抛出异常
}
if(Object.prototype.toString.call(str) === "[object Number]"){
//抛异常后,停止向下执行了,直接运行catch代码
throw "出错了!这个不是字符串,数字类型是没split方法属性的";
}
var arr = str.split(',');
return arr;
} catch (error) {
console.error(error);//输出自定义的异常信息
return [];
}
}
getStringToArray(undefined);//输出:【出错了!这个不是字符串,undefined / null是没任何属性的】
getStringToArray(null);//输出:【出错了!这个不是字符串,undefined / null是没任何属性的】
getStringToArray(123);//输出:【出错了!这个不是字符串,数字类型是没split方法属性的】
getStringToArray("篮球,足球,排球");
场景二: 终止forEach的循环 。利用try/catch/throw禁用代码执行。注意:Promise.reject(‘错误信息’)只能阻止当前函数内往下执行。
var arr = [1,2,3,4,5];
try {
arr.forEach(element => {
if(element === 3){
throw '循环终止了';
}
console.log('数字: ', element);
});
} catch (error) {
console.error(error);//输出异常信息:循环终止了
}
**场景三:**在vue项目中,首页大屏的组件地址是可配置的,为防止用户输入错误的组件地址,导致无法加载页面路由组件,进不了页面。需要用require预加载一次,try/catch捕获,异常就重新赋值可用的路由组件地址。
//后端返回的菜单数据
var menuData = [
{
"path": "/dashboard/analysis",
"component": "dashboard/Analysis",
"route": true,
"meta": {
"external": false,
"keepAlive": false,
"icon": "home",
"permissionList": [
{}
],
"componentName": "Analysis",
"title": "首页"
},
"name": "dashboard-analysis",
"id": "1374671776843169794"
},
//{...},
//{...},
//{...},
];
menuData.forEach(element => {
//预加载大屏组件地址,防止无效的组件地址,导致页面白屏,进不了系统
if (element.path === "/dashboard/analysis") {
try {
require('@/views/' + element.component);//测试加载大屏组件
} catch (error) {
console.error(`配置了无效的大屏组件地址【${element.component}】:`, error);
element.component = 'dashboard/*******';//重新设置有效的大屏组件
}
}
});
//vue组件,组件地址输入框校验的部分代码如下
export default {
data() {
return {
rules: {
component: [
{
required: true,
message: '请输入组件地址',
trigger: 'change'
},
{
validator(rule, value, callback) {
if (value) {
try {
require('@/views/' + value);//测试加载大屏组件
return callback();
} catch (error) {
//代码内不存在该组件
return callback(new Error('组件地址不正确'));
}
} else {
return callback(new Error('组件地址不能为空'));
}
}, trigger: 'blur'
},
]
}
}
},
methods: {}
}
**场景四:**输入框,用户输入字母表达式,要想知道表达是否正确,可以用try/catch/eval对表达式进行处理
var express = 'a + b + (c * e)';//用户在输入框,输入的表达式
var arr = "abcdefghijklmnopqrstuvwxyz".split("");
arr.forEach((element,index) => {
express = express.replaceAll(element,index + 1);//将字母替换成数字,
});
try {
eval(express);//将字符串(数字)运算,合法则通过
} catch (error) {
//不通过校验
new Error(`计算公式异常,转换后无法计算`);
}
**场景五:**输入框输入json数据字符串(请求头header),try/cath捕获异常进行校验。
var str = "{a:111,b:}";
try {
JSON.parse(str);//
} catch (error) {
console.log(new Error(`json数据不正确`));
}
**场景六:**数据不可控,容易出错,需要加try/cath捕获异常。
try {
var data = [];//后端返回比较复杂且不确定
for (let i = 0; i < data.length; i++) {
const element = data[i];
//数据处理、转换,可能会出错
}
} catch (error) {
alert('数据处理出错了!');
}
捕获不了的异常。注:外层的try/catch无法捕获异步队列微任务、宏任务内的异常,要想捕获宏任务内的异常,try/catch代码只能写在微任务、宏任务代码内。 如果try块作用域内执行setTimeout方法,从setTimeout定时器里面把错误err信息throw扔出来,catch外部是不能捕获的,因为setTimeout是在临时寄存器上执行的,所以不在一个栈上处理上下文的,错误err无法被捕获。
try {
(async function(){
//加了async后try捕获不到函数内的异常了。去掉async后catch就捕获异常了
var num = undefined;
num.toString();//错误代码,由浏览器抛出异常
})();
} catch (error) {
console.error('异常输出:',error);//没捕获到异常
}
function getData() {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cdn.bootcss.com/vue/2.6.14/vue.min.js', false);
xhr.onreadystatechange = function () {
//异步代码,不能捕获异常(宏任务)
// readyState == 4说明请求已完成
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 304) {
resolve();
var str = undefined;
str.split(',');//错误代码,由浏览器抛出异常
}
}
}
xhr.send();
});
}
(async function () {
try {
setTimeout(() => {
//定时器内的异常不被捕获(宏任务)
var str = undefined;
str.join(',');//错误代码,由浏览器抛出异常
}, 100);
Promise.resolve().then(() => {
//then(微任务)
var arr = null
arr.push(111);//错误代码,由浏览器抛出异常
});
await getData().then(() => {
//await then函数内,能捕获异常,同一栈上处理上下文,能捕获异常
var num = undefined;
num.toString();
});
} catch (error) {
console.error('异常输出:', error);//没输出
}
})();