js统一异常捕获

dhso
2018/05/28 10:41
统计中

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;
        }
    };
}

本文为 dhso 原创

发布在 http://blog.minws.com/reacttong-yi-yi-chang-bu-huo/

如有转载,请标明来源!

作者信息
姓名:dhso
热评文章
最新评论
文章概览