快速了解JavaScript的错误处理

JavaScript错误处理.png

编程语言都会需要完善的错误处理策略使得应用程序更为合理的操作错误。错误处理在服务端的处理较为完善,但是浏览器端进展较为缓慢,不同浏览器的错误处理方式也不同,且默认的错误处理方式对用户也不友好。因此,必须理解各种捕获和处理错误的方式。而在 ECMA-262 的第3版中增加了 try-catch 语句块和 throw 语句来处理错误,以及一些错误类型来描述错误。

try-catch

ECMA-262 新增的错误处理方式与 Java 相似,将可能出错的代码放在 try 子句中,而处理错误的代码放在 catch 子句中:

try {
    // Possible error code
} catch (e) {
    // Error Handler
}

catch 子句中捕获到的错误对象包含发生错误的相关信息,通过该错误对象可以获取错误类型的 name 属性和保存错误消息的 message 属性,e.message 即可调用。

在使用 try-catch 语句块时,要知道什么时候使用最好。如果发生无法控制的错误上,就需要使用 try-catch 语句块来处理错误;如果明确知道代码会发生某种错误,就要采用相应的操作来防止错误发生,而不是使用 try-catch 语句块来处理错误。

finally

try-catch 语句块中,无论是 try 子句执行完,还是 catch 子句执行完,都可以接着执行 finally 子句中的代码,trycatch 都无法阻止,包括 return 语句。

function test(){
    try {
        return 1;
    } catch (e){
        throw e;
    } finally {
        return false;
    }
}

上面的方法,最后会返回 false

<small>注意:主要代码中包含了 finally 子句,try 块或 catch 块中的 return 语句就会被忽略,理解这一点很重要。在使用 finally 时一定要仔细确认代码的行为。</small>

抛出错误

使用 throw 抛出错误是另一种错误处理方式。throw 抛出任意表达式。如下所示:

throw "Not Value Error";        // String type error
throw 31;                       // Number type error
throw false;                    // Boolean type error
throw { name: "JavaScript" };   // Object type error

也可以调用 Error 构造函数来生成一个错误对象抛出,接收的值为错误消息。如下所示:

throw new Error("Null value Error.");

也可以调用特定的错误类型生成一个错误对象并抛出。如 SyntaxErrorTypeError 等。使用 ES6 中的继承语法创建错误类型也可以,这样需要提供 name 属性和 message 属性。如下所示:

class CustomError extends Error {
    constructor(message) {
        super(message);
        this.name = "CustomError";
        this.message = message;
    }
}
throw new CustomError("Null Value Error.");

这种方式有助于在捕获错误时更精准地区分错误。

Error

Error 错误类型是基本类型,其它错误类型基本都是继承该类型。Error 提供了一个构造方法用来创建实例对象,当发生错误时,Error 通过构造方法创建实例对象并被抛出。

throw new Error("Null Value Error.");

Error 错误类型提供了三个属性:

  • name:字符串类型。表示错误名称。
  • message:字符串类型。表示错误信息。
  • stack:字符串类型。表示错误的堆栈。

ECMA-262 总共定义了 8 种错误类型,除了 Error 通用的错误类型外,还有如下几种类型:

  • EvalError:该错误类型会在使用 eval() 函数发生错误时抛出。
  • InternalError:该错误类型主要会在底层 JavaScript 引擎抛出异常时由浏览器抛出。如递归过多导致栈溢出。通常并不是需要处理的错误。
  • RangeError:该错误类型会在数值变量或参数越界时抛出。
  • ReferenceError:该错误类型会在引用无效时抛出。
  • SyntaxError:该错误类型会在 eval() 在解析代码的过程中发生。
  • TypeError:该错误类型会在变量或参数不是预期类型,或者访问不存在的方法时抛出。
  • URIError:该错误类型只会在使用 encodeURI()decodeURI() ,并且传入的 URI 格式错误时发生。

浏览器很少会抛出 Error 类型的错误,主要是开发者抛出的自定义错误。而其它错误类型可以使用 instanceof 进行判断。如下所示:

try {
    // Possible error code
} catch (e) {
    if (e instanceof TypeError) {
        // Type Error Handler
    } else if (e instanceof ReferenceError) {
        // Reference Error Handler
    } else {
        // Other Error Handler
    }
}

error 事件

没有被 try-catch 捕获的错误都会在 window 对象上触发 error 事件。该事件会传入几个参数:

  • message:错误消息。
  • url:发生错误的 URL
  • line:错误的行号。
  • colno:错误的列号。
  • errorError对象。
window.onerror = (message, url, line, colno, error) => {
    // 可以对错误的消息进行处理,这里打印在控制台上
    console.log(message);
    return false; // 这里返回 false 来阻止浏览器默认报告错误的行为
};

通过返回 false,函数实际上变成整个文档的 try/catch 语句,可以捕获所有未处理的运行时错误。适当的 try-catch 语句块意味着不会有错误到达浏览器这个 层次,因此就不会触发 error 事件。当返回 true,会阻止执行默认事件处理函数。

而有一些资源加载失败,会触发一个 error 事件,这个事件遵循 DOM 格式。因此可以使用 addEventListener 捕获。

const image = new Image();
image.addEventListener("error", (event) => {
    console.log("Image not loaded!");
});
image.src = "resource.gif"; // 不存在,资源会加载失败。

总结

一个设计良好的错误处理对编程语言十分重要。JavaScript 提供的 try-caththrow 两种处理错误的方式。但是两种错误处理方式,有不同的错误场景要求。如果编写的库或函数需要知道错误发生的具体原因,就抛出异常;如果确切知道接下来的操作,就捕获错误。而没有通过 try-catch 处理的错误,可以使用 window.onerror 事件来处理。

更多内容请关注公众号「海人为记

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355

推荐阅读更多精彩内容