处理异步异常
任何程序都会出错,因此,错误处理在编程中是很重要的一环。尽管,一般错误主要逻辑是存在于服务器端的(因为服务端的应用程序一般都是一直运行着的,错误处理对于应用程序稳定性来说十分重要);但是当浏览器中 JavaScript 脚本发生错误时,浏览器的报告错误方式一般不大讨人喜,这样可能会导致用户的流失之类的。
再者,了解异常的生成和处理对于一个程序的运行也是一种知识的积累。
出现异常会发生什么?
我们知道JavaScript是一门解释性语言,并没有编译时( complie time ),是彻头彻尾的运行时( Runtime ),因此程序的错误异常只会在运行时发生,这意味着程序出现这种错误后,后续的代码将不能够正常执行。
console.log('script start');
function func() {
console.log('some calc');
throw new Error('something wrong');
}
func();
console.log('scripit end');
// script start
// some calc
// Uncaught Error: something wrong
因此,对于用户来说,这意味着当前页面可能是无法使用的状态,这样会导致用户体验的下降。
生成异常 throw
通常来说,很多程序语言生成错误都是使用 抛出
来生成一个内置错误对象或自定义错误对象;当然语法和 Java 如此相像的 JavaScript 也不例外,使用 throw
关键字抛出自定义错误对象。
ECMA-262定义了以下8种错误类型:
Error
InternalError ( passed, only in IE !!! )
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
EvalError.prototype instanceof Error && EvalError.prototype instanceof Error && RangeError.prototype instanceof Error && ReferenceError.prototype instanceof Error && SyntaxError.prototype instanceof Error && TypeError.prototype instanceof Error && URIError.prototype instanceof Error
// true
其中 Error
是后7种的基类,其他错误累心继承自该类型;而且浏览器中很少会抛出 Error 类型的错误,类型主要用于开 发者抛出自定义错误。而后7种错误类型基本来自于浏览器内置抛出。
抛出一些错误!
window.onerror = (message, url, line) => {
console.log('error event');
console.log('message: ', message);
console.log('url: ', url);
console.log('line: ', line);
};
console.log('script start');
function globalFn() {
console.log('globalFn exec');
function localFn() {
console.log('localFn exec');
throw new Error('something wrong inside!');
console.log("won't console!");
}
localFn();
console.log("won't console!");
}
globalFn();
console.log('script end');
// script start
// globalFn exec
// localFn exec
// error event
// message: Uncaught
// Error: something wrong inside!
// url: http://localhost:63342/vsProj/%E5%85%AB%E8%82%A1%E6%96%87/html/19-exception.html?_ijt=rhmk5di4q8fnp6g8nbm7ttqcbm&_ij_reload=RELOAD_ON_SAVE
// line: 21
// Uncaught Error: something wrong inside!
由上,异常若不处理不仅影响当前上下文;若当前上下文不对错误进行处理,会继续抛给更上一层的上下文直到浏览器上下文,浏览器会将在出现错误的代码处停止运行,在 console 中打印相应的message。同时,浏览器(window对象)一直在监听一个 error
事件,当错误(未经过处理)出现时触发该事件。
处理异常 try/catch
JavaScript 处理异常也和 Java 一样,使用 try
和 catch
语句。
console.log('script start');
function globalFn() {
console.log('globalFn exec');
function localFn() {
console.log('localFn exec');
throw new Error('something wrong inside!');
// 因为在该上下文并没有直接处理错误,抛给了上一级上下文 globalFn,
// 导致后续代码不会打印
console.log("do not catch, won't console!");
}
try{
localFn();
}
console.log("after caught in globalFn ctx, console!");
}
globalFn();
console.log('script end');
// script start
// globalFn exec
// localFn exec
// after caught in globalFn ctx, console!
// script end
很重要的一点是 try...catch
只能处理运行中的错误(源代码必须是可以执行的),因为 JavaScript 引擎在解析期( parse-time )要确保源代码是能够执行的,该时间段出现的错误被称为解析时间错误,这种错误会使得整个 script 都不可以执行,必须移除这些错误。
// 整个源代码都不会执行
try {
{{{ // 不匹配括号
}catch(e) {
console.log("won't console!");
}finally {
console.log("won't console!");
}
try {
const
}catch(e) {
console.log("won't console!");
}finally {
console.log("won't console!");
}
// output:
// Uncaught SyntaxError: Unexpected token '}' (at
finally
比 return
优先级高:
function func() {
try {
return 'try';
}catch{
}finally{
return 'higher than try';
}
}
console.log(func()); // higher than try;
Reference
- test cloudflare cache. 24hours