当前位置: 首页 > 后端技术 > Node.js

节点错误处理及日志

时间:2023-04-03 13:46:40 Node.js

node项目中的错误处理使用node中的Error对象使用captureStackTrace方法添加内置的错误信息//Error对象自带的属性Error.captureStackTrace//captureStackTrace的使用方法varobj={message:'somethingiswrong'}Error.captureStackTrace(obj)throwobj//此时会抛出obj对象的message中的信息。使用trycatch来捕获错误。直接在trycatch中写代码捕获错误信息可以使用下面的方法functionfoo(params,cb){consterror=newError('somethingiswrong')if(error)cb(error)}使用上面的回调方法比较麻烦和容易出错做错误处理。现在node已经支持asyncawait,所以尽量使用它们。asyncfunctionfoo(){try{awaitbar()}catch(e){console.log(e)}}asyncfunctionbar(){thrownewError('asyncfunctiongotwrong)}foo()基本错误类型项目中会有多个地方处理错误信息,所以先写一个基本错误类型,方便使用//基本错误类型classHttpBaseErrorextendsError{constructor(httpStatusCode,httpMsg,errCode,msg){super(`HTTPERROR:${消息}`);this.httpStatusCode=httpStatusCode;this.httpMsg=httpMsg;这个.errCode=错误代码;}}try{//直接抛出定义的错误thrownewHttpBaseError(404,'资源不存在',10000,'资源未找到');}catch(e){console.log(e.message);控制台日志(e.httpStatusCode);控制台日志(e.httpMsg);console.log(e.errCode);}除了具体错误类型的基本类型外,在不同的情况下会有不同的错误信息,需要使用特定的错误类型来处理具体的错误信息//一个参数errortypeconstERROR_CODE=40000//错误码classHttpRequestParamErrorextendsHttpBaseError{constructor(paramName,desc,msg){super(200,desc,ERROR_CODE,`${paramName}wrong:${msg}`)}}这样就是非常方便调用这个错误类型返回参数错误的错误。在错误抛出的逻辑错误处理中,模型和控制器中的一些错误是不能直接返回给用户的,应该只返回给模型或控制器的调用者对普通的接口、控制器、模型错误使用错误处理,使用设置的错误类型进行处理,比如前面写的HttpRequestParamError,在所有路由的最后,需要使用一个错误处理器来集中所有的错误//errorhandlerfunctionhandler(options){returnfunction(err,req,res,next){if(errinstanceofHttpRequestParamError){//这里针对不同的错误做不同的处理console.log('httprequesterror')res.statusCode=err.httpStatusCoderes.json({code:err.errCode,msg:err.httpMsg})}else{//设置以外的错误,将管理权交给外部next(err)}}}可预测错误除外,未知类型的错误,需要一个未知的错误处理程序来处理剩余的错误functionunKnowErrorHandler(options){returnfunction(err,req,res,next){console.log(err)res.json({code:99999,msg:'unKnowerror'})}}在节点中使用控制台调试日志是没有问题的,但是在线上环境下,我们无法有效的看到控制台,还是使用日志系统比较方便调试在线,记录信息等winston的使用winston是node中常用的日志插件constwinston=require('winston')constlogger=winston.createLogger({transports:[newwinston.transports.Console(),newwinston.transports.File({name:'info_logger',//日志名称filename:'logs/info.log',//日志记录文件地址level:'info'//设置日志类型}),//第二个记录器,记录错误级别日志newwinston.transports.File({name:'error_logger',filename:'logs/error.log',level:'error'})]});//错误级别高于info,error.log文件只会记录错误日志logger.error('firsterrorlogwithwinston')//的信息文件会记录info级别的日志和高于info级别的日志,比如errorlogger.info('firstinfologwithwinston')logrotation(日志轮换)在产生大量数据的应用中,logs的输出是一个数量大,这是需要对日志进行拆分,比如按照每天的频率分别记录日志winston没有自带日志轮转,需要导入winston-daily-rotate-file库const{createLogger,format,transports}=require('winston');const{combine,timestamp,label,prettyPrint}=format;require('winston-daily-rotate-file')vartransport=new(transports.DailyRotateFile)({文件名:'./logs/app-%DATE%.log',datePattern:'YYYY-MM-DD-HH',maxSize:'20m',maxFiles:'14d',格式:combine(label({label:'rightmeow!'}),timestamp(),prettyPrint()),});transport.on('rotate',function(oldFilename,newFilename){});varlogger=createLogger({transports:[transport]});logger.info('HelloWorld!');运行日志文件,在logs目录下生成今天的日志。欢迎访问我的博客