2、Error实例被创建时不能被称之为异常,只有在使用throw关键字将其抛出时才会引发异常;
new Error('出错了!');
console.log('我吃嘛嘛香,喝嘛嘛棒!'); // 正常输出 '我吃嘛嘛香,喝嘛嘛棒!'
3、技术上来讲,你可以抛出任何类型的异常,而不仅仅是Error的实例,但请不要这么做,总是抛出正确的错误对象会让我们更容易定位问题,同时可以保持错误处理的一致性,捕获异常时候也总能够拿到Error实例上的message和stack;
// bad
throw '出错了';
throw 123;
throw [];
throw null;
异常捕获
前面有提到如果引发异常后不做任何处理会冒泡似的在你的调用栈中向顶部传播,直到导致当前任务崩溃。有时候发生致命错误时候我们确实希望安全的停止程序的运行,如果希望程序得以恢复一般我们会用到try...catch...finally代码结构,它是js中处理异常的标准方式;
try {
// 要运行的代码,可能引发异常
doSomethingMightThrowError();
}
catch (error) {
// 处理异常的代码块,当发生异常时将会被捕获,如果不继续throw则不会再向上传播
// error为捕获的异常对象
// 这里一般能让程序恢复的代码
doRecovery();
}
finally {
// 无论是否出现异常,始终都会执行的代码
doFinally();
}
被忽略的finally:此语句块会在try和catch语句结束之后执行,无论结果是否报错。
同时要注意,异步中的发生的异常无法被上层捕获,比如:
// Timeout
try {
setTimeout(() => {
throw Error("定时器出错了!");
}, 1000);
} catch (error) {
console.error(error.message);
}
// Events
try {
window.addEventListener("click", function() {
throw Error("点击事件出错了!");
});
} catch (error) {
console.error(error.message);
}
Promise本身是就可以捕获异常,语法上也类似于try catch,一旦发生异常,程序跳过promise内的代码继续执行;可以使用了catch方法捕获后进行处理,也可以使用then方法中的第二个参数处理异常。promise的异常对象同样是冒泡的,前者捕获了就不会抛给后者,参见示例:
const promiseA = new Promise((resolve,reject)=>{
throw new Error('Promise出错了!');
});
const doSomethingWhenResolve = () => {};
const doSomethingWhenReject = (error) => {
logger.log(error)
}
// 使用catch捕获
const promiseB = promiseA.then(doSomethingWhenResolve).catch(doSomethingWhenReject);
// 等价于
const promiseB = promise.then(doSomethingWhenResolve, doSomethingWhenResolve);
promiseB.then(() => {
console.log('我又可以正常进到then方法了!');
}).catch(()=>{
console.log('不会来这里!');
})