js统一异常捕获

2018-05-28 / 0 评论 / 166 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年10月27日,已超过1121天没有更新,若内容或图片失效,请留言反馈。

window.onerror全局异常捕获

window.onerror = function (msg, url, line){
         // 可以捕获异步函数中的错误信息并进行处理,提示Script error.
    console.log(msg);   // 获取错误信息
    console.log(url);   // 获取出错的文件路径
    console.log(line);  // 获取错误出错的行数
};
setTimeout(function() {
    console.log(obj);   // 可以被捕获到,并在onerror中处理
}, 200);

try-catch运行时解决方案

try{
    // 单一作用域try...catch可以捕获错误信息并进行处理
    console.log(obj);
}catch(e){
    console.log(e); //处理异常,ReferenceError: obj is not defined
}
try{
    // 不同作用域不能捕获到错误信息
    setTimeout(function() {
        console.log(obj); // 直接报错,不经过catch处理
    }, 200);
}catch(e){
    console.log(e);
}
// 同一个作用域下能捕获到错误信息
setTimeout(function() {
    try{
        // 当前作用域try...catch可以捕获错误信息并进行处理
        console.log(obj);
    }catch(e){
        console.log(e); //处理异常,ReferenceError: obj is not defined
    }
}, 200);

ES6 Class的异常捕获方案

/**
 * 封装React方法的错误处理,改成使用入参的prototype中是否有render生命周期函数来判断
 * @param  {object} Component 传入组件
 * @return {object} 返回包裹后的组件
 */
function _defineReact(Component) {
    var proto = Component.prototype;
    var key;
    // 封装本身constructor中的构造方法,React组件编译为ES5后是一个构造函数,ES6下面为class
    if (_isTrueFunction(Component)) {
        Component = wrapFunction(Component);
    }
    var componnetKeys = Object.getOwnPropertyNames(proto);
    // 支持ES6类的属性方法错误捕获
    for (var i = 0, len = componnetKeys.length; i < len; i++) {
        key = componnetKeys[i];
        proto[key] = wrapFunction(proto[key])
    }
    // 支持ES5下的属性方法错误捕获
    for (key in proto) {
        if (typeof proto[key] === 'function') {
            proto[key] = wrapFunction(proto[key]);
        }
    }
    return Component;
}
/**
 * 判断是否为真实的函数,而不是class
 * @param  {Function} fn [description]
 * @return {Boolean}     [description]
 */
function _isTrueFunction(fn) {
    var isTrueFunction = false;
    try {
        isTrueFunction = fn.prototype.constructor.arguments === null;
    } catch (e) {
        isTrueFunction = false;
    }
    for (var key in fn.prototype) {
        return false;
    }
    return isTrueFunction;
}
class component extends React.Component {
    componentDidMount(){
        var a = {};
        console.log(a.b.c);
    }
    render() {
        return <div>hello world</div>;
    }
}
export default _defineReact(component);

Promise内的错误捕获

// 如果浏览支持Promise,捕获promise里面then的报错,因为promise里面的错误onerror和try-catch都无法捕获
if (Promise && Promise.prototype.then) {
    var promiseThen = Promise.prototype.then;
    Promise.prototype.then = function(resolve, reject) {
        return promiseThen.call(this, _wrapPromiseFunction(resolve), _wrapPromiseFunction(reject));
    }
}
/**
 * 输入一个函数,将函数内代码包裹进try-catch执行,then的resolve、reject和普通函数不一样
 *
 * @param {any} fn
 * @returns 一个新的函数
 */
function _wrapPromiseFunction(fn) {
    // 如果fn是个函数,则直接放到try-catch中运行,否则要将类的方法包裹起来,promise中的fn要返回null,不能返回空函数
    if (typeof fn !== 'function') {
        return null;
    }
    return function () {
        try {
            return fn.apply(this, arguments);
        } catch (e) {
            _errorProcess(e);
            throw e;
        }
    };
}

0

评论 (0)

取消