美文网首页
javascript的异常处理

javascript的异常处理

作者: id被吃 | 来源:发表于2017-10-14 10:33 被阅读15次

    先了解一下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

    相关文章

      网友评论

          本文标题:javascript的异常处理

          本文链接:https://www.haomeiwen.com/subject/eukxuxtx.html