让你满头黑线的错误,这么看


一、错误这个东西

  • 太多的时候javascript报出的错误,都是没有上下文的.比如object expected.非常难调试.

  • 此时就需要我们自定义错误处理机制,清晰明确的搞明白错误的位置.


二、错误类型

1.常见错误

  • SyntaxError(语法错误)

解析代码时发生的语法错误
var 1a // Uncaught SyntaxError: Invalid or unexpected token

  • Uncaught ReferenceError:引用错误

引用了不存在的变量
a() // Uncaught ReferenceError: a is not defined
console.log(b) // Uncaught ReferenceError: b is not defined

  • RangeError:范围错误,当值超出有效范围时发生的错误

Number对象的方法参数超出范围
var num = new Number(12.34)
console.log(num.toFixed(-1)) // Uncaught RangeError: toFixed() digits argument must be between 0 and 20 at Number.toFixed

  • TypeError 类型错误

变量或参数不是预期类型时发生的错误,或者访问不存在的方法.
let obj = {};
obj.say() // Uncaught TypeError: obj.say is not a function
let o = new 10;

  • URIError,URL错误

decodeURI("%"); // Uncaught URIError: URI malformed
该错误,主要是以下几个函数涉及的 encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()

  • ReferenceError 引用错误

当一个不存在的变量被引用时发生的错误
var a = 10;
console.log(a);
console.log(b); // Uncaught ReferenceError: b is not defined

  • EvalError eval()函数执行错误,ES5+基本看不到的错误.

Error是基类型,其它错误都继承该类型,故所有的错误都共享相同的属性.
Error一般浏览器不会抛出,主要用于开发者抛出自定义错误.

new Error([message[,fileName[,lineNumber]]])
第一个参数表示错误提示信息,第二个是文件名,第三个是行号。

三、错误捕获

1. 错误定义和抛出

  • throw 操作符用于抛出自定义错误.
  • 必须有一个值,但类型不限.
  • 一旦抛出错误,代码就会停止执行.
  throw  12345;
  throw 'Hello world';
  throw new Error('some bad');
  throw new SyntaxError('语法错误');
  throw new TypeError('类型错误');
  throw new RangeError('值超出有效范围');
  throw new URIError('URI错误')
  throw new ReferenceError('引用错误');
  • 通过继承Error可以自定义错误类型
    class customError extends Error {
      constructor(message) {
        super(message);
        this.name = 'customError';
        this.message = message;
      }
    }
    throw new customError('自定义错误类型')

2. 代码中怎么抛出

  • 如果是有几千行代码的web应用程序,想找到错误就比较难,此时可以使用自定义错误,有效的提高代码的可维护性.
  • 抛出错误的目的,是为错误提供有关其发生原因的说明
    function process(values) {
      if (!(values instanceof Array)) {
        throw new Error('process(): Argument must be an array');
      }
      values.sort();
    }

    process(123)

3. 捕获错误

  • 应该在明确知道一旦错误了,后面要怎么做时,才去捕获错误.
  • 捕获错误的目的在于阻止浏览器以其默认方式相应.
try{
  // 可能出错的代码块
}catch(error){
  // 出错的时候要做什么
}
  • 调用不存在的函数
    try {
      fn()
    } catch (error) {
      console.log('An error happened', error);

    }

4. error事件

  • 凡是没有被try/catch语句处理的错误都会触发window.error事件.
   // html代码
   <p onclick="fn()">error</p>
  // js代码
    window.onerror = function (mesage, url, line) {
      console.log(mes, url, line);
      return true;
    }
  // message 错误信息
  // url 错误发生的url
  // line 错误发生行号
  // return true 组织浏览器默认的报错行为.
  • 图片加载失败,也可触发error事件,遵循DOM格式,返回event对象
    const image = new Image();
    image.addEventListener('load', event => {
      console.log('image loaded');

    })

    image.addEventListener('error', (eve) => {
      alert('图片加载失败....')

    })
    image.src = 'xxx.gif';
  • 静态资源文件,如js,css的加载
// js代码
// 此处使用DOM2级绑定,才能监听错误
 window.addEventListener('error', function (eve) {
      console.log(eve, '滴滴,获取错误');
      if (eve) {
        let target = eve.target || eve.srcElement;
        let isElementTarget = target instanceof HTMLElement;
        if (!isElementTarget) {
          // js错误
          console.log('滴滴,js错误');
          // 获取错误信息
          let { filename, message, lineno, colno, error } = e;
          let { message: ErrorMsg, stack } = error;
        } else {
          // 页面静态资源加载错误处理
          console.log('滴滴,静态文件错误');
          let { type, timeStamp, target } = eve;
          let { localName, outerHTML, tagName, src } = target;
          let typeName = target.localName;
          let sourceUrl = "";
          if (typeName === "link") {
            sourceUrl = target.href;
          } else if (typeName === "script") {
            sourceUrl = target.src;
          }
          confirm('资源加载失败,换个网络或者刷新页面(' + sourceUrl + ')')
        }
      }
      // 设为true表示捕获阶段调用,
      return true;
    }, true);
   //  html代码
  <script type="text/javascript" src="a.js"></script>
  <script type="text/javascript" src="b.js"></script>  
  

一定注意要把js文件的引入放到下方,测试否则无效.

  • 公司中使用 监控系统,推荐sentry

四 项目中的使用

1. 记录错误

  • web项目中,经常建立错误日志存储和跟踪系统,也可记录js错误.
  • 需要在服务器上有处理js错误的相关程序,该程序只用从查询字符串中获取数据,保存到日志中即可.
   function logError(sev,msg){
          let img = new Image(),
          encodedSev = encodeURIComponent(sev),
          encodedMsg = encodeURIComponent(msg);
          img.src = `log.php?sev=${encodedSev}&msg=${encodedMsg}`
  }
  // sev 严重程度  msg 错误信息
  // 使用img对象发送请求,不收跨域的限制,且也比较少的出错.
  • 用到 try/catch的地方,都可以记录
  for(let mod of mods){
      try{
         mod.init();
         }catch(ex){
           logError('nonfatal','Module init failed:${ex.message}')
        }
   }

2. 错误抛出的使用

  • 抛出错误,可以方便我们一眼看出代码问题,可以减少额外的工作量.

  • 大型网站中,通常用assert() 函数抛出错误.

   //  抛出错误的函数 
    function assert(condition, message) {
      if (!condition) {
        throw new Error(message)
      }
    }
   // 如果类型不符合要求则直接抛出错误
    function divide(num1, num2) {
      assert(typeof num1 == 'number' && typeof num2 == 'number', 'divide():Both arguments must be numbers.');

      return num1 / num2;
    }

    console.log(divide(12, 'af'));

最后

  • try/catch,可以通过更合适的方式处理错误,避免浏览器处理.
  • 所有没有被try/catch处理的错误都会被window.onerror事件处理.更多的判断静态文件,是否加载成功.



别跑,据说给我一键三联的人写代码都没Bug! 您的支持就是我最大的动力!

我是飞翔,
愿您日有所长.

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值