(Javascript)错误处理,“try...catch“,Error对象,自定义异常,再次抛出异常,finally,全局catch

错误处理,“try…catch”

try {
  // 执行此处代码
} catch(err) {
  // 如果发生错误,跳转至此处
  // err 是一个 error 对象
} finally {
  // 无论怎样都会在 try/catch 之后执行
}

try…catch 仅对运行时的 error有效
  • 要使得 try..catch 能工作,代码必须是可执行的。如果代码包含语法错误,那么 try..catch 将无法正常工作。

try…catch 同步工作
  • 如果在"计划的"代码中发生异常,则不会捕获到
//try..catch 包裹了稍后要执行的函数,这时引擎已经离开了try..catch结构
try {
  setTimeout(function() {
    noSuchVariable; // 脚本将在这里停止运行
  }, 1000);
} catch (e) {
  alert( "won't work" );
}
  • 想要捕获到计划的函数中的异常,那么 try..catch 必须在这个函数内
setTimeout(function() {
  try {
    noSuchVariable; // try..catch 处理 error 了!
  } catch {
    alert( "error is caught here!" );
  }
}, 1000);

Error 对象

属性:

  • name:Error名称(对于一个未定义的变量,名称是 “ReferenceError”。)
  • message:关于 error 的详细文字描述。
  • stack:当前的调用栈:用于调试目的的一个字符串,其中包含有关导致 error 的嵌套调用序列的信息。
try {
  lalala; // error, variable is not defined!
} catch(err) {
  alert(err.name); // ReferenceError
  alert(err.message); // lalala is not defined
  alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)

  // 也可以将一个 error 作为整体显示出来as a whole
  // Error 信息被转换为像 "name: message" 这样的字符串
  alert(err); // ReferenceError: lalala is not defined
}

可选的"catch"绑定
  • 如果我们不需要 error 的详细信息,catch 也可以忽略它:
try {
  // ...
} catch { // <-- 没有 (err)
  // ...
}

使用"try…catch"
  • 如果 json 格式错误,JSON.parse 就会生成一个 error
  • 所以要捕获到这个异常,输出错误信息
let json = "{ bad json }";

try {

  let user = JSON.parse(json); // <-- 当出现一个 error 时...
  alert( user.name ); // 不工作

} catch (e) {
  // ...执行会跳转到这里并继续执行
  alert( "Our apologies, the data has errors, we'll try to request it one more time." );
  alert( e.name );
  alert( e.message );
}

自定义异常

"Throw"操作符
  • throw 操作符会生成一个error对象

语法:throw <error object>

内建的标准error的构造器
  • Error、SyntaxError、ReferenceError、TypeError等。

语法:

let error = new Error(message);
// 或
let error = new SyntaxError(message);
let error = new ReferenceError(message);
// ...
  • 对于内建的error;name属性是构造器的名字;message来自参数。
let error = new Error("Things happen o_O");

alert(error.name); // Error
alert(error.message); // Things happen o_O
代码
  • 如果解析字符串产生的user对象缺少name属性,抛出异常
let json = '{ "age": 30 }'; // 不完整的数据

try {

  let user = JSON.parse(json); // <-- 没有 error

  if (!user.name) {
    throw new SyntaxError("Incomplete data: no name"); // (*)
  }

  alert( user.name );

} catch(e) {
  alert( "JSON Error: " + e.message ); // JSON Error: Incomplete data: no name
}

再次抛出(rethrowing)

在上面的例子中,我们使用 try..catch 来处理不正确的数据。但是在 try {...} 块中是否可能发生 另一个预料之外的 error?例如编程错误(未定义变量)或其他错误,而不仅仅是这种“不正确的数据”。

let json = '{ "age": 30 }'; // 不完整的数据

try {
  user = JSON.parse(json); // <-- 忘记在 user 前放置 "let"

  // ...
} catch(err) {
  alert("JSON Error: " + err); // JSON Error: ReferenceError: user is not defined
  // (实际上并没有 JSON Error)
}
catch 应该只处理它知道的 error,并“抛出”所有其他 error。

“再次抛出(rethrowing)”技术可以被更详细地解释为:

  • Catch 捕获所有 error。
  • 在 catch(err) {…} 块中,我们对 error 对象 err 进行分析。
  • 如果我们不知道如何处理它,那我们就 throw err。

通常,我们可以使用 instance 操作符判断错误类型

let json = '{ "age": 30 }'; // 不完整的数据
try {

  let user = JSON.parse(json);

  if (!user.name) {
    throw new SyntaxError("Incomplete data: no name");
  }

  blabla(); // 预料之外的 error

  alert( user.name );

} catch(e) {

  if (e instanceof SyntaxError) {
    alert( "JSON Error: " + e.message );
  } else {
    throw e; // 再次抛出 (*)
  }
}
  • 如果不知到如何处理这个异常,可以再次抛出,被外部的try…catch结构捕获
function readData() {
  let json = '{ "age": 30 }';

  try {
    blabla(); // error!
  } catch (e) {
    if (!(e instanceof SyntaxError)) {
      throw e; // 再次抛出(不知道如何处理它)
    }
  }
}

try {
  readData();
} catch (e) {
  alert( "External catch got: " + e ); // 捕获了它!
}

try…catch…finally

  • finally如果存在,它在所有情况下都会被执行(无论函数以return还是throw完成都无关紧要)
try {
   ... 尝试执行的代码 ...
} catch(e) {
   ... 处理 error ...
} finally {
   ... 总是会执行的代码 ...
}
  • 如果我们使用 let 在 try 块中声明变量,那么该变量将只在 try 块中可见。

try…finally
  • 当我们不想在这儿处理 error(让它们 fall through),但是需要确保我们启动的处理需要被完成。
function func() {
  // 开始执行需要被完成的操作(比如测量)
  try {
    // ...
  } finally {
    // 完成前面我们需要完成的那件事儿,即使 try 中的执行失败了
  }
}

使用finally的优势

比较下面两个代码片段:

try {
  work work
} catch (e) {
  handle errors
} finally {
  cleanup the working space
}
try {
  work work
} catch (e) {
  handle errors
}

cleanup the working space
  • 当try…catch中有return(或throw)时,finally中的代码肯定会执行,第二种中后面的语句肯定不会执行

全局catch

  • 在 try…catch 结构外有一个致命的 error,然后脚本死亡了。这个 error 就像编程错误或其他可怕的事儿那样。
  • message:Error信息
  • url:发生error的脚本的URL
  • line、col:发生error处的代码的行号和列号
  • error:Error对象
window.onerror = function(message, url, line, col, error) {
  // ...
};

例:

<script>
  window.onerror = function(message, url, line, col, error) {
    alert(`${message}\n At ${line}:${col} of ${url}`);
  };

  function readData() {
    badFunc(); // 啊,出问题了!
  }

  readData();
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值