error

1.addEventListener

window.addEventListener('error', (error) => {
  console.log('我知道 404 錯誤了');
  console.log(
    error
  );
  return true;
}, true);

 2.onerror

throw new Error('拋出異常');  //拋出異常
window.onerror = function (msg, url, row, col, error) {
	Access-Control-Allow-Origin:*
  console.log('我知道錯誤了');
  console.log({
    msg,  url,  row, col, error
  })
  return true; // 注意,在返回 true 的時候,異常纔不會繼續向上拋出error;
};

//條件
//1.服務器設置Access-Control-Allow-Origin的響應頭
//2.<script crossorigin></script>  使得加載的跨域腳本可以得出跟同域腳本同樣的報錯信息

3. promise+unhandledrejection

new Promise(function(resolve, reject) {
  reject(new Error('haha'))  
  })
/瀏覽器自帶unhandledrejection事件監聽全局沒有catch的Promise執行
  window.addEventListener('unhandledrejection', function(err) {
     console.log(err);
  });

4.AST

var fs = require('fs');
var _ = require('lodash');
var UglifyJS = require('uglify-js');

var isASTFunctionNode = function (node) {
    return node instanceof UglifyJS.AST_Defun || node instanceof UglifyJS.AST_Function;
}

var globalFuncTryCatch = function (inputCode, errorHandler) {
    if(!_.isFunction(errorHandler)){
        throw 'errorHandler should be a valid function';
    }
    var errorHandlerSource = errorHandler.toString();
    var errorHandlerAST = UglifyJS.parse('(' + errorHandlerSource + ')(error);');
    var tryCatchAST = UglifyJS.parse('try{}catch(error){}');
    var inputAST = UglifyJS.parse(inputCode);
    var topFuncScope = [];

    //將錯誤處理函數包裹進入catch中
    tryCatchAST.body[0].bcatch.body[0] = errorHandlerAST;

    //蒐集所有函數
    var walker = new UglifyJS.TreeWalker(function (node) {
        if (isASTFunctionNode(node)) {
            topFuncScope.push(node);
        }
    });
    inputAST.walk(walker);

    //對函數進行變換, 添加try catch語句
    var transfer = new UglifyJS.TreeTransformer(null,
        function (node) {
            if (isASTFunctionNode(node) && _.includes(topFuncScope, node)) {
                //函數內部代碼蒐集
                var stream = UglifyJS.OutputStream();
                for (var i = 0; i < node.body.length; i++) {
                    node.body[i].print(stream)
                }
                var innerFuncCode = stream.toString();

                //清除try catch中定義的多餘語句
                tryCatchAST.body[0].body.splice(0, tryCatchAST.body[0].body.length);

                //用try catch包裹函數代碼
                var innerTyrCatchNode = UglifyJS.parse(innerFuncCode, {toplevel: tryCatchAST.body[0]});

                //獲取函數殼
                node.body.splice(0, node.body.length);

                //生成有try catch的函數
                return UglifyJS.parse(innerTyrCatchNode.print_to_string(), {toplevel: node});
            }
        });
    inputAST.transform(transfer);
    var outputCode = inputAST.print_to_string({beautify: true});
    return outputCode;
}

module.exports.globalFuncTryCatch = globalFuncTryCatch;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章