JavaScript的Console扩展和输出级别控制

    xiaoxiao2021-03-25  123

    扩展Console的原由

    目前网上还没有类似的教程哦。 Console作为日志输出调试的功能还是很强大的。可以打印正常的日志信息,错误信息(log,info,warn,error)等等,还可以详细详细显示函数调用栈,信息的输出函数名以及代码位置,功能可谓非常强大。 但是有个问题就是无法根据日志的等级来自由控制输出权限。比如我设置一个等级,只能输出warn和error这样。虽然有可能发布的时候,会把Console基本有从代码中去掉,但是调试的时候有时也需要调整等级了。比如想暂时把log给屏蔽掉,只输出info或者warn以上信息。

    最开始是想写个Log日志类来扩展Console的,增加控制日志等级之类的功能。写好之后,发现一个很郁闷的问题,那就是自己的日志输出,远远没有Console自带的强大。因为Console输出信息的时候,可以把当前类和那一行代码的信息给打印出来。这个很强大,对于调试非常有用,而自己写的Log没有这个功能。 用自己的Log进行扩展,则无法显示出真实的代码路径,变成自己写的Log路径了。看下图 当然这个输出日志路径是方便本地调试看。如果需要把日志错误等信息收集发给服务器,自定义扩展Log还是可行的。 针对这样的情况,我对Console对象进行了扩展。增加了相应的功能。

    Console增加等级控制和扩展分析

    演示代码为TypeScript的代码。后面会给出完整的TypeScript和JavaScript的代码。

    1日志输出等级控制

    首先是准备增加等级控制,比如我可以调整日志的输出级别,来决定trace,log,info,error等输出。原理其实很简单,利用原型重写对应的方法。根据等级,把小于日志输出等级的方法设置为一个空方法,什么也不做,这样就无法输出信息了。 对输出方法进行分级别

    /** 调试级别,trace函数路径 **/ static TRACE:number = 0; /** 普通日志级别 **/ static LOG:number = 1; /** 信息日志级别 **/ static INFO:number = 2; /** 警告日志级别 **/ static WARN:number = 3; /** 错误日志级别 **/ static ERROR:number = 4; /** 需要屏蔽覆盖的方法名 **/ private static funNames:string[] = ["trace","log","info","warn","error"];

    实现过程是这样的: 先把console原来的trace,log等function给存放起来,当进行等级控制时,先把所有的方法都设置为空方法,然后把大于等于日志级别的方法给恢复过来。

    //设置回最初的方法 for(var i:number = 0; i < this.funNames.length; i++) { //定义个空方法屏蔽掉 console[this.funNames[i]] = this.emptyFun; } //根据this.$level来还原输出方法 for(var i:number = this.$level; i < this.funNames.length; i++) { //还原成最初的方法 console[this.funNames[i]] = this.funList[i]; }

    原理就是这么简单,然后进行包装的代码就会稍微多一点。看输出效果。

    // //开启扩展日志 asf.ConsolePlus.init(); console.log("扩展日志的正常模式"); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); // console.error("error的信息"); console.log("把日志等级调整为WANR"); //设置日志等级,warn,就只有warn的信息才能输出 asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); console.error("error的信息");

    输出结果是这样的 可以看到把日志等级调整为WARN之后,就无法看到log和info的信息了。

    强化Console的输出方法

    这个实现其实主要是后期扩展,需要把日志传给服务器或者其他调试端的时候才需要的。主要原理其实是在原有的log,info等方法的后面增加自己的信息(当然也可以发给服务器)。类似java的AOP面向切面编程。

    /** * 创建扩展函数 * @param oldFun 原有的函数 * @param funName 函数名称 */ private static createPlusFun(oldFun:Function,funName:string):void { var fun:Function = function (message?: any, ...optionalParams: any[]):void { console.group("[" + funName + "][" + new Date() + "]"); oldFun.apply(console,arguments); console.groupEnd(); } this.funPulsList.push(fun); } asf.ConsolePlus.openConsolePlus(); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息");

    前后增加了个组显示的简单扩展,看具体的输出效果。

    完整的TypeScritp和JavaScript代码

    TypeScritp代码

    /** * Created by sodaChen on 2017/3/1. */ namespace asf { /** * 输出信息扩展类 * @author sodaChen * Date:2017/2/15 */ export class ConsolePlus { /日志级别 /** 调试级别,trace函数路径 **/ static TRACE:number = 0; /** 普通日志级别 **/ static LOG:number = 1; /** 信息日志级别 **/ static INFO:number = 2; /** 警告日志级别 **/ static WARN:number = 3; /** 错误日志级别 **/ static ERROR:number = 4; /** 默认是最初的日志级别,改变这个值。可以改变日志输出的结果 **/ private static $level:number = ConsolePlus.LOG; /** 是否开启扩展模式 **/ private static isPlusMode:boolean; /** 需要屏蔽覆盖的方法名 **/ private static funNames:string[] = ["trace","log","info","warn","error"]; /** console最初的方法缓存 **/ private static funList:Function[]; /** 扩展后的方法级别 **/ private static funPulsList:Function[]; /** 空方法 **/ private static emptyFun:Function; static init(isPlusMode:boolean = false):void { this.funList = []; this.funPulsList = []; this.emptyFun = function(){}; //存放原来的方法 for(var i:number = 0; i < this.funNames.length; i++) { this.funList.push(console[this.funNames[i]]); } //生成新的扩展方法 for(var i:number = 0; i < this.funNames.length; i++) { this.createPlusFun(this.funList[i],this.funNames[i]); } this.setConsoleMode(isPlusMode); } /** * 设置日志等级,所有大于等于这个日志级别的输出都可以正常输出,小于的则不能进行输出 * @param level */ static setLevel(level:number):void { this.$level = level; this.openConsole(); } /** * 设置输出模式 * @param isPlusMode 是否为扩展模式 */ static setConsoleMode(isPlusMode:boolean):void { this.isPlusMode = isPlusMode; if(isPlusMode) this.openConsolePlus(); else this.openConsole(); } /** * 打开日志 */ static openConsole():void { this.closeConsole(); //扩展默认,则调用扩展方法 if(this.isPlusMode) { this.openConsolePlus(); return ; } for(var i:number = this.$level; i < this.funNames.length; i++) { //还原成最初的方法 console[this.funNames[i]] = this.funList[i]; } } /** * 关闭所有的日志输出 */ static closeConsole():void { //设置回最初的方法 for(var i:number = 0; i < this.funNames.length; i++) { //定义个空方法屏蔽掉 console[this.funNames[i]] = this.emptyFun; } } /** * 开启日志输出的扩展模式 */ static openConsolePlus():void { this.isPlusMode = true; //扩展console的所有方法 for(var i:number = this.$level; i < this.funNames.length; i++) { console[this.funNames[i]] = this.funPulsList[i]; } } /** * 关闭日志输出的扩展模式 */ static closeConsolePlus():void { this.isPlusMode = false; //还原成原来的方法 this.openConsole(); } /** * 创建扩展函数 * @param oldFun 原有的函数 * @param funName 函数名称 */ private static createPlusFun(oldFun:Function,funName:string):void { var fun:Function = function (message?: any, ...optionalParams: any[]):void { console.group("[" + funName + "][" + new Date() + "]"); oldFun.apply(console,arguments); console.groupEnd(); } this.funPulsList.push(fun); } } }

    完整的调试信息代码:

    // //开启扩展日志 asf.ConsolePlus.init(); console.log("扩展日志的正常模式"); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); // console.error("error的信息"); console.log("把日志等级调整为WANR"); //设置日志等级,warn,就只有warn的信息才能输出 asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); console.error("error的信息"); //设置回正常的log级别 asf.ConsolePlus.setLevel(asf.ConsolePlus.LOG); console.log("启动Console的扩展模式"); asf.ConsolePlus.openConsolePlus(); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); console.error("error的信息"); //输出扩展模式也支持日志等级的 console.log("Console的扩展模式调整日志级别到warn"); asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN); console.log("log的信息"); console.info("info的信息"); console.warn("warn的信息"); console.error("error的信息"); asf.ConsolePlus.closeConsolePlus(); console.log("1关闭Console的扩展模式,正常输出啦"); //得调级别才能输出log asf.ConsolePlus.setLevel(asf.ConsolePlus.LOG); console.log("2关闭Console的扩展模式,正常输出啦");

    JavaScript代码

    注意,这个js代码是TypeScript生成的代码,所以有部分会很奇怪。具体我没单独调试运行过,请注意。

    var asf; (function (asf) { /** * 输出信息扩展类 * @author sodaChen * Date:2017/2/15 */ var ConsolePlus = (function () { function ConsolePlus() { } ConsolePlus.init = function (isPlusMode) { if (isPlusMode === void 0) { isPlusMode = false; } this.funList = []; this.funPulsList = []; this.emptyFun = function () { }; //存放原来的方法 for (var i = 0; i < this.funNames.length; i++) { this.funList.push(console[this.funNames[i]]); } //生成新的扩展方法 for (var i = 0; i < this.funNames.length; i++) { this.createPlusFun(this.funList[i], this.funNames[i]); } this.setConsoleMode(isPlusMode); }; /** * 设置日志等级,所有大于等于这个日志级别的输出都可以正常输出,小于的则不能进行输出 * @param level */ ConsolePlus.setLevel = function (level) { this.$level = level; this.openConsole(); }; /** * 设置输出模式 * @param isPlusMode 是否为扩展模式 */ ConsolePlus.setConsoleMode = function (isPlusMode) { this.isPlusMode = isPlusMode; if (isPlusMode) this.openConsolePlus(); else this.openConsole(); }; /** * 打开日志 */ ConsolePlus.openConsole = function () { this.closeConsole(); //扩展默认,则调用扩展方法 if (this.isPlusMode) { this.openConsolePlus(); return; } for (var i = this.$level; i < this.funNames.length; i++) { //还原成最初的方法 console[this.funNames[i]] = this.funList[i]; } }; /** * 关闭所有的日志输出 */ ConsolePlus.closeConsole = function () { //设置回最初的方法 for (var i = 0; i < this.funNames.length; i++) { //定义个空方法屏蔽掉 console[this.funNames[i]] = this.emptyFun; } }; /** * 开启日志输出的扩展模式 */ ConsolePlus.openConsolePlus = function () { this.isPlusMode = true; //扩展console的所有方法 for (var i = this.$level; i < this.funNames.length; i++) { console[this.funNames[i]] = this.funPulsList[i]; } }; /** * 关闭日志输出的扩展模式 */ ConsolePlus.closeConsolePlus = function () { this.isPlusMode = false; //还原成原来的方法 this.openConsole(); }; /** * 创建扩展函数 * @param oldFun 原有的函数 * @param funName 函数名称 */ ConsolePlus.createPlusFun = function (oldFun, funName) { var fun = function (message) { var optionalParams = []; for (var _i = 1; _i < arguments.length; _i++) { optionalParams[_i - 1] = arguments[_i]; } console.group("[" + funName + "][" + new Date() + "]"); oldFun.apply(console, arguments); console.groupEnd(); }; this.funPulsList.push(fun); }; /日志级别 /** 调试级别,trace函数路径 **/ ConsolePlus.TRACE = 0; /** 普通日志级别 **/ ConsolePlus.LOG = 1; /** 信息日志级别 **/ ConsolePlus.INFO = 2; /** 警告日志级别 **/ ConsolePlus.WARN = 3; /** 错误日志级别 **/ ConsolePlus.ERROR = 4; /** 默认是最初的日志级别,改变这个值。可以改变日志输出的结果 **/ ConsolePlus.$level = ConsolePlus.LOG; /** 需要屏蔽覆盖的方法名 **/ ConsolePlus.funNames = ["trace", "log", "info", "warn", "error"]; return ConsolePlus; }()); asf.ConsolePlus = ConsolePlus; })(asf || (asf = {}));

    完整的调试代码可以直接用上面那个ts的调试代码,使用过程是完全一样。(ts生成出来的那部分js也是一样的,不帖了)

    转载请注明原文地址: https://ju.6miu.com/read-5261.html

    最新回复(0)