异常处理

    除内置的 Error 类外,还有一些额外的内置错误,它们继承自 Error 类:

    当数字类型变量或者参数超出其有效范围时,出现 RangeError 的错误提示:

    1. // 使用过多参数调用 console
    2. console.log.apply(console, new Array(1000000000)); // RangeError: 数组长度无效

    ReferenceError

    当引用无效时,会出现 ReferenceError 的错误提示:

    1. 'use strict';
    2. console.log(notValidVar); // ReferenceError: notValidVar 未定义

    当解析无效 JavaScript 代码时,会出现 SyntaxError 的错误提示:

    1. 1 *** 3 // SyntaxError: 无效的标记 *

    TypeError

    变量或者参数不是有效类型时,会出现 TypeError 的错误提示:

    当传入无效参数至 encodeURI()decodeURI() 时,会出现 URIError 的错误提示:

    1. decodeURI('%'); // URIError: URL 异常
    1. try {
    2. } catch (e) {
    3. console.log(e);
    4. }

    不要这么做,使用 对象的基本好处是,它能自动跟踪堆栈的属性构建以及生成位置。

    原始字符串会导致极差的调试体验,并且在分析日志时,将会变得错综复杂。

    传递一个 Error 对象是没问题的,这种方式在 Node.js 回调函数中非常常见,它用第一个参数作为错误对象进行回调处理。

    1. function myFunction (callback: (e: Error)) {
    2. doSomethingAsync(function () {
    3. if (somethingWrong) {
    4. callback(new Error('This is my error'));
    5. } else {
    6. callback();
    7. }
    8. })
    9. }

    「Exceptions should be exceptional」是计算机科学中常用用语。这里有一些原因说明在 JavaScript(TypeScript) 中也是如此。

    不清楚从哪里抛出错误

    考虑如下代码块:

    下一个开发者可能并不清楚哪个函数可能会抛出错误。在没有阅读 task1/task2 代码以及他们可能会调用的函数时,对代码 review 的人员可能也不会知道错误会从哪里抛出。

    1. try {
    2. const foo = runTask1();
    3. } catch (e) {
    4. console.log('Error:', e);
    5. }
    6. try {
    7. } catch (e) {
    8. }

    但是现在,如果你想从第一个任务中传递变量到第二个任务中,代码会变的混乱(注意:foo 变量需要用 let 显式注解它,因为它不能从 runTask1 中返回出来):

    1. let foo: number; // Notice 使用 let 并且显式注名类型注解
    2. try {
    3. foo = runTask1();
    4. } catch (e) {
    5. console.log('Error:', e);
    6. }
    7. try {
    8. const bar = runTask2();
    9. } catch (e) {
    10. console.log('Error:', e);
    11. }

    没有在类型系统中很好的表示

    考虑如下函数:

    1. function validate(value: number) {
    2. if (value < 0 || value > 100) {
    3. throw new Error('Invalid value');
    4. }

    在这种情境下使用 Error 不是一个好的主意。因为没有用来验证函数的类型定义(如:(value: number) => void),取而代之一个更好的方式是创建一个验证方法:

    现在它具有类型定义了。

    TIP

    除非你想用以非常通用(try/catch)的方式处理错误,否则不要抛出错误。