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

来源:互联网 发布:水利工程造价软件下载 编辑:程序博客网 时间:2024/05/04 07:21

扩展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的扩展模式,正常输出啦");//得调级别才能输出logasf.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也是一样的,不帖了)

0 0
原创粉丝点击