javascript的异常处理

先了解一下javascript原生的异常类型

1、SyntaxError //解析代码时发生的语法错误
2、ReferenceError //引用一个不存在的变量时发生的错误
3、RangeError //当一个值超出有效范围时发生的错误
4、TypeError //变量或参数不是预期类型时发生的错误
5、URIError //URI相关函数的参数不正确时抛出的错误
6、EvalError //eval函数没有被正确执行时,会抛出EvalError错误
7、Error:最普通的异常

Error对象

JavaScript原生提供一个Error构造函数,所有抛出的错误都是这个构造函数的实例。Error对象的实例必须含有message属性,提示出错的信息:

var err = new Error('出错了');
err.message // "出错了"

此外,部分javascript引擎还提供了其他两个非标准的属性
1.name : 错误名称
2.stack : 错误的堆栈

自定义异常

除了上述提到的原生异常类型,javascript还允许我们自己定制异常,通过创建一个异常对象,然后让其继承Error对象即可

function newError(message){
  this.message = message;
  this.name = "newError";
}
newError.prototype = new Error();
newError.prototype.constructor = newError;
var demo = new newError("自定义异常");

try-catch结构

try {
  //...
} catch (e) {
  console.log(e.name + ": " + e.message);
  console.log(e.stack);
}

try语句内存放的是需要检测异常的代码段,catch代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。
比如:

openFile();
try{
  writeFile(); //检测函数运行是否异常
}catch(e){
  handleError(e); //捕获到异常后处理
}

try-catch-finally结构

引入finally的目的是为了让代码更加健壮,finally内的代码段是必须执行的部分,不过在代码运行出现异常和没有异常的场合下执行的方式不同:假如try语句内代码未出现异常,那么正常执行finally内的代码段;如果出现了异常,那么先执行catch内的异常处理,后执行finally内的语句。
接着上面的例子:

openFile();
try{
  writeFile(); //检测函数运行是否异常
}catch(e){
  handleError(e); //捕获到异常后处理
}finally{
  closeFile();
}

注意:如果catch内含有return,那么出现异常时先执行catch内位于return之前的代码,catch内return语句后的代码不会执行,然后跳转到finally。

抛出异常-throw

throw语句的作用是中断程序执行,抛出一个意外或错误。它接受一个表达式作为参数,可以抛出各种值。

function throwIt(exception) {
 try {
   throw exception;
 } catch (e) {
   console.log('Caught: '+ e);
 }
}

throwIt(3);
// Caught: 3
throwIt('hello');
// Caught: hello
throwIt(new Error('An error happened'));
// Caught: Error: An error happened

加入判断语句:

var n = 100;

try {
  throw n;
} catch (e) {
  if (e <= 50) {
    // ...
  } else {
    throw e;
  }
}

catch在捕获到throw抛出的异常后,还是按照原本方式执行

异常类型的检测

上述我们已经有了在try-catch语句内加入判断的例子,生活中有时我们需要针对不同的异常做不同的处理,就可以借鉴前面的方式。

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.log(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.log(e.name + ": " + e.message);
  }
  // ...
}

全局异常处理window.onerror

上述提到的try-catch(finally)结构只适合在代码块内执行,无法做到全局异常检测,window.onerror可以做到。
结构:

window.onerror = function (message, source, lineno, colno, error) { }

message:异常信息(字符串)
source:发生异常的脚本URL(字符串)
lineno:发生异常的行号(数字)
colno:发生异常的列号(数字)
error:Error对象(对象)

兼容性:IE9及以下只支持前面3个参数
Chrome 13+
Firefox 6.1+
Safari 5.1+
Opera 11.61+
IE10+
都支持全部

try {
    setTimeout(() => {
        throw new Error("some message");
    }, 0);
} catch (err) {
    console.log(err);
}
/*******/
window.onerror = (msg, url, line, col, err) => {
    console.log(err);
}
setTimeout(() => {
    throw new Error("some message");
}, 0);
// Error: some message

列出一个window.onerror的兼容性写法:

window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) {
    var errorStr = '', error = {};
    error.errorMessage = errorMessage;
    error.scriptURI = scriptURI;
    error.lineNumber = lineNumber;
    error.columnNumber = columnNumber || '';
    error.errorObj = errorObj || '';
    error.userAgent = window.navigator.userAgent;
    error.pageUrl = window.location.href;
    errorStr = ' errorMessage: ' + error.errorMessage + '\n scriptURI: ' + error.scriptURI
                + '\n lineNumber: ' + error.lineNumber + '\n columnNumber: ' + error.columnNumber
                + '\n errorDescription: ' + error.errorDescription + '\n userAgent: ' + error.userAgent
                + '\n pageUrl: ' + error.pageUrl;
    
    console.log(errorStr);
    new Image().src = '/errorLog/index';
}

在chrome中,window.onerror能检测从别的域引用的脚本文件中的异常,并且将这些异常标记为Script error,如果不想处理其他域的脚本文件,可以在代码中用Script error标记将其过滤。然而如果异常被try-catch包裹,chrome也无法检测到异常。在其他浏览器中不会引入跨域js异常,也只能获取到一个简单的 Script Error信息,没有什么实际意义。

解决方案:
1.给应用内所需的<script>标签添加 crossorigin 属性,比如:<script type=”text/javascript” src=”/error.js” crossorigin></script>;
2.在 js 所在的 cdn 服务器上添加 Access-Control-Allow-Origin: *HTTP 头;
3.使用 throw new Error(“error message here”)。
<script>
    window.onerror = function () {
        console.log(arguments)
        return true;
    }
    throw new Error('show error');
</script>
Paste_Image.png

值得一提的是,页面中可能有好几个 script 标签, window.onerror 这个错误监听一定要放到最前头,否则将监听不到错误。如果将throw new Error放前头,throw new Error('show error');将直接报错,也就无法往下执行

参考:http://javascript.ruanyifeng.com/grammar/error.html
https://segmentfault.com/a/1190000011481099#articleHeader4
https://github.com/hawx1993/tech-blog/issues/13
http://www.frontfans.com/archives/139
http://caibaojian.com/toutiao/7963

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

推荐阅读更多精彩内容