前因
对于前端,出了错以后一般是在浏览器控制台打印错误日志。
这样比较被动,如果出错以后,能实时将错误信息上报给服务器将会对前端服务质量有更好的监控。
常见的js错误有如下几种:
(1) SyntaxError
SyntaxError是解析代码时发生的语法错误
// 变量名错误
var 1a;
// 缺少括号
console.log ('hello');
(2)ReferenceError
ReferenceError是引用一个不存在的变量时发生的错误。
unknownVariable
// ReferenceError: unknownVariable is not defined
另一种触发场景是,将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值。
console.log() = 1
// ReferenceError: Invalid left-hand side in assignment
this = 1
// ReferenceError: Invalid left-hand side in assignment
上面代码对函数console.log的运行结果和this赋值,结果都引发了ReferenceError错误
(3)RangeError
RangeError是当一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。
new Array(-1)
// RangeError: Invalid array length
(1234).toExponential(21)
// RangeError: toExponential() argument must be between 0 and 20
(4)TypeError
TypeError是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。
new 123
//TypeError: number is not a func
var obj = {}; obj.unknownMethod()
// TypeError: undefined is not a function
上面代码的第二种情况,调用对象不存在的方法,会抛出TypeError错误。
(5)URIError
URIError是URI相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。
decodeURI('%2')
// URIError: URI malformed
(6)EvalError
eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再在ES5中出现了,只是为了保证与以前代码兼容,才继续保留。
以上这6种派生错误,连同原始的Error对象,都是构造函数。开发者可以使用它们,人为生成错误对象的实例。
new Error("出错了!");
new RangeError("出错了,变量超出有效范围!");
new TypeError("出错了,变量类型无效!");
针对如下错误范围定义普通的js错误上报机制 :
window.onerror = function(message, url, line) {
if (!url) return;
var msg = {};
//记录客户端环境
msg.ua = window.navigator.userAgent;
msg.message = message.message;
msg.url = url;
msg.line = line;
msg.page = window.location.href;
//上报服务器
new Image().src = '/service/jsErrReport?errJson=' + encodeURIComponent(JSON.stringify(msg)) + '&t=' + Math.random();
};
但是在angular.js中 有默认的错误处理方案:
即是在$exceptionHandler
工厂中用$log.error
将错误堆栈信息打印在控制台。
因此,我们要做的就是覆盖默认的方法,在顶层app中添加如下代码:
//覆盖默认的处理机制
//全局错误拦截并上报
app.factory('$exceptionHandler',function () {
return function errorCatcherHandler(exception, cause) {
var msg = {
ua: window.navigator.userAgent,
message: exception.message,
stack: exception.stack,
cause: cause,
url: location.href
};
console.error(exception);
new Image().src = '/service/jsErrReport?errJson=' + encodeURIComponent(JSON.stringify(msg)) + '&t=' + Math.random();
};
});
最后,还有一种错误是服务器的请求错误,也可以添加拦截器处理:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(httpInterceptor);
} ]);
httpInterceptor.$inject = ['$q'];
function httpInterceptor($q, UserControlService) {
return {
responseError: function (response) {
console.log('responseError................................', response);
//在此处记录服务器请求的错误信息
return $q.reject(response);
}
};
}
effevo技术团队出品 (https://effevo.com)