错误处理方案
/**
* 如果我们有一个函数, 在调用这个函数时, 如果出现了错误, 那么我们应该是去修复这个错误.
*/
function sum(num1, num2) {
// 当传入的参数的类型不正确时, 应该告知调用者一个错误
if (typeof num1 !== "number" || typeof num2 !== "number") {
// return undefined
throw "parameters is error type~"
}
return num1 + num2
}
// 调用者(如果没有对错误进行处理, 那么程序会直接终止)
// console.log(sum({ name: "why" }, true))
console.log(sum(20, 30))
console.log("后续的代码会继续运行~")
throw关键字
throw 表达式就是在 throw 后面可以跟上一个表达式来表示具体的异常信息。
throw 后面可以跟基本数据类型,也可以跟对象,主要是跟对象,因为表达的信息多。
class HYError {
constructor(errorCode, errorMessage) {
this.errorCode = errorCode // 错误代号
this.errorMessage = errorMessage // 错误信息
}
}
function foo(type) {
console.log("foo函数开始执行")
if (type === 0) {
// 1.抛出一个字符串类型(基本的数据类型)
// throw "error"
// 2.比较常见的是抛出一个对象类型
// throw { errorCode: -1001, errorMessage: "type不能为0~" }
// 3.也可以自定义抛出的类:创建类, 并且创建这个类对应的对象
throw new HYError(-1001, "type不能为0~")
// 强调: 如果函数中已经抛出了异常, 那么后续的代码都不会继续执行了
console.log("foo函数后续的代码")
}
console.log("foo函数结束执行")
}
foo(0)
// foo函数开始执行
// G:\JavaScript\demo\index.js:19
// throw new HYError(-1001, "type不能为0~")
// ^
// HYError { errorCode: -1001, errorMessage: 'type不能为0~' }
Error 类型
事实上,JavaScript 已经给我们提供了一个 Error 类,我们可以直接创建这个类的对象:
Error 包含三个属性:
- messsage:创建Error对象时传入的message;
- name:Error 的名称,通常和类的名称一致;
stack:整个 Error 的错误信息,包括 message 和函数的调用链,这个链是从加载模块开始的;
- 当我们直接打印 Error 对象时,打印的就是 stack 属性; ```javascript function foo(type) { console.log(“foo函数开始执行”)
if (type === 0) { // 可以修改错误名称 const err = new Error(‘构造函数中默认的是错误信息,比如:不能为 0’) err.name = ‘类型错误’ // 也可以修改 stack 整个 Error 错误信息 throw err }
console.log(“foo函数结束执行”) }
foo(0)
// foo函数开始执行 // G:\JavaScript\demo\index.js:9 // throw err // ^
// 类型错误: 构造函数中默认的是错误信息,比如:不能为 0
// at foo (G:\JavaScript\demo\index.js:6:17)
// at Object.
Error有一些自己的子类,表示了更具体的错误类型,我们也可以继承 Error 从而定义自己错误类型类。
- RangeError:下标值越界时使用的错误类型;
- SyntaxError:解析语法错误时使用的错误类型;
- TypeError:出现类型错误时,使用的错误类型;
```javascript
function foo(type) {
console.log("foo函数开始执行")
if (type === 0) {
throw new TypeError('不能为0')
}
console.log("foo函数结束执行")
}
foo(0)
// foo函数开始执行
// TypeError: 不能为0
// 略
JS 处理异常的过程
try-catch 异常捕获
很多情况下当出现异常时,我们并不希望程序直接推出,而是希望可以正确的处理异常:这个时候我们就可以使用try catch
function foo(type) {
if (type === 0) {
throw new Error("foo error message~")
}
}
// 两种处理方法:
// 1.第一种是不处理, 那么异常会进一步的抛出, 直到最顶层的调用
// 如果在最顶层也没有对这个异常进行处理, 那么我们的程序就会终止执行, 并且报错
// 2.使用try catch来捕获异常
function bar() {
try {
foo(0)
console.log("bar函数后续的继续运行")
} catch(err) { // catch 可以接收一个参数,该参数固定为 Error 类的实例对象
console.log("err:", err.message)
} finally {
console.log("finally代码执行~, close操作")
}
}
function test() {
// 因为异常会层层向上抛出,所以也可以在上层进行异常捕获
// try {
bar()
// } catch (error) {
// console.log("error:", error)
// }
}
function demo() {
test()
}
demo()
// 异常被捕获,不影响后续代码的执行
console.log("后续的代码执行~")
// err: foo error message~
// finally代码执行~, close操作
// 后续的代码执行~
在ES10(ES2019)中,catch后面绑定的error可以省略。
如果有一些必须要执行的代码,我们可以使用finally来执行:finally表示最终一定会被执行的代码结构;
- 注意:如果 try 和 finally 中都有返回值,那么会使用 finally 当中的返回值; ```javascript function foo(type) { if (type === 0) { throw new Error(‘foo error message~’) } }
function bar() { try { foo(1) console.log(‘bar函数后续的继续运行’)
return 123
} catch (err) { console.log(‘err:’, err.message) } finally { console.log(‘finally代码执行~, close操作’)
return 456
} }
console.log(bar()) // 456
console.log(‘后续的代码执行~’)
// bar函数后续的继续运行
// finally代码执行~, close操作
// 456
// 后续的代码执行~
```