node错误处理与日志记录的实现


Posted in Javascript onDecember 24, 2018

node项目中的错误处理

node中Error对象的使用

使用captureStackTrace方法加入自带的错误信息

// Error对象自带的属性
Error.captureStackTrace

// 如何使用captureStackTrace
var obj = {
  message: 'something is wrong'
}

Error.captureStackTrace(obj)

throw obj  // 此时会抛出obj对象的message内信息

使用try catch捕获错误

直接把代码写在try catch中即可捕获错误信息

try{
  throw new Error('oh no')
}catch(e){
  console.log(e)
}

在异步代码中,直接try catch是无法捕获错误信息的,可以使用如下方法

function foo(params, cb){
  const error = new Error('something is wrong')
  if(error) cb(error)
}

以上使用callback方式来做错误处理比较容易麻烦,容易出错,现在node已经支持async await所以尽量使用它们准没错

async function foo(){
  try{
    await bar()
  }catch(e){
    console.log(e)
  }
}

async function bar(){
  throw new Error('async function got wrong)
}

foo()

基本错误类型

在项目会有多个地方对错误信息进行处理,所以先写一个基本错误类型,方便使用

// 基本错误类型
class HttpBaseError extends Error {
 constructor(httpStatusCode, httpMsg, errCode, msg) {
  super(`HTTP ERROR: ${msg}`);
  this.httpStatusCode = httpStatusCode;
  this.httpMsg = httpMsg;
  this.errCode = errCode;
 }
}

try {
// 直接抛出定义好的错误即可
 throw new HttpBaseError(404, '资源不存在', 10000, 'resouse is not found');
} catch (e) {
 console.log(e.message);
 console.log(e.httpStatusCode);
 console.log(e.httpMsg);
 console.log(e.errCode);
}

特定错误类型

除了基本类型,不同情况下会有不同错误信息,需要用一个特定的错误类型来处理特定的错误信息

// 一个参数错误类型
const ERROR_CODE = 40000  // 错误码
class HttpRequestParamError extends HttpBaseError {
  constructor(paramName, desc, msg) {
    super(200, desc, ERROR_CODE, `${paramName} wrong: ${msg}`)
  }
}

这样,在参数错误的地方就能非常方便的调用这个错误类型来返回错误

抛错的逻辑

错误处理中,model,controller中的错误,有些是不能直接返回给用户的,应该只返回给model或controller的调用者。

使用错误处理

正常接口,controller,model的错误,使用设定好的错误类型进行处理,例如前面写的HttpRequestParamError,在所有所有路由的最后,需要使用一个error handler来对所有的错误进行集中处理

// error handler
function handler(options) {
  return function (err, req, res, next) {
    if (err instanceof HttpRequestParamError) {  // 这里对不同的错误做不同的处理
      console.log('http request error')
      res.statusCode = err.httpStatusCode
      res.json({
        code: err.errCode,
        msg: err.httpMsg
      })
    } else {
      // 设定之外的错误,把管理权向外移交
      next(err)
    }
  }
}

除了可预知的错误,还有未知的类型的错误,此时需要一个unknow error handler进行剩余错误的处理

function unKnowErrorHandler(options) {
  return function (err, req, res, next) {
    console.log(err)
    res.json({
      code: 99999,
      msg: 'unKnow error'
    })
  }
}

node中的日志

平时使用console来debug是没有问题的,但是在线上环境,我们并不能有效的看到console,使用日志系统可以更好的方便线上的debug,记录信息等

winston的使用

winston是node中常用的日志插件

const winston = require('winston')

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({
      name: 'info_logger',  // log名称
      filename: 'logs/info.log',  // 日志记录文件地址
      level: 'info' // 设置log的类型
    }),
    // 第二个logger,记录error级别的log
    new winston.transports.File({
      name: 'error_logger',
      filename: 'logs/error.log',
      level: 'error'
    })
  ]
});

// error级别比info要高,error.log文件只会记录error日志
logger.error('first error log with winston')
// info文件内会记录info级别的log和比info级别高的log,比如error
logger.info('first info log with winston')

日志滚动(log rotation)

在产生大量数据的应用当中,日志的输出是大量的,这是就需要对日志进行拆分处理,例如按照每天的频率来分别记录日志。

winston并不自带log rotation,需要引入winston-daily-rotate-file库

const {
  createLogger,
  format,
  transports
} = require('winston');
const {
  combine,
  timestamp,
  label,
  prettyPrint
} = format;
require('winston-daily-rotate-file')


var transport = new(transports.DailyRotateFile)({
  filename: './logs/app-%DATE%.log',
  datePattern: 'YYYY-MM-DD-HH',
  maxSize: '20m',
  maxFiles: '14d',
  format: combine(
    label({
      label: 'right meow!'
    }),
    timestamp(),
    prettyPrint()
  ),
});
transport.on('rotate', function (oldFilename, newFilename) {});

var logger = createLogger({
  transports: [
    transport
  ]
});

logger.info('Hello World!');

运行日志文件,此时在logs目录下就生成了今天的日志

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
身份证号码前六位所代表的省,市,区, 以及地区编码下载
Apr 12 Javascript
Jquery 表单取值赋值的一些基本操作
Oct 11 Javascript
jquery实现九宫格大转盘抽奖
Nov 13 Javascript
javascript省市区三级联动下拉框菜单实例演示
Nov 29 Javascript
JS传值出现中文参数乱码的解决方法
Jun 30 Javascript
jQuery插件Flexslider实现图片轮播、图文结合滑动切换效果
Apr 16 Javascript
js 数据存储和DOM编程
Feb 09 Javascript
vue ssr 指南详读
Jun 29 Javascript
vue-cli V3.0版本的使用详解
Oct 24 Javascript
Angular事件之不同组件间传递数据的方法
Nov 15 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
Aug 26 Javascript
vue-cropper组件实现图片切割上传
May 27 Vue.js
详解如何在vscode里面调试js和node.js的方法步骤
Dec 24 #Javascript
@angular前端项目代码优化之构建Api Tree的方法
Dec 24 #Javascript
微信小程序获取用户openid的实现
Dec 24 #Javascript
vue-router启用history模式下的开发及非根目录部署方法
Dec 23 #Javascript
小程序实现人脸识别功能(百度ai)
Dec 23 #Javascript
优雅的elementUI table单元格可编辑实现方法详解
Dec 23 #Javascript
基于webpack4.X从零搭建React脚手架的方法步骤
Dec 23 #Javascript
You might like
php数组声明、遍历、数组全局变量使用小结
2013/06/05 PHP
解析coreseek for sphinx的使用
2013/06/21 PHP
基于PHP实现的事件机制实例分析
2015/06/18 PHP
使用SyntaxHighlighter实现HTML高亮显示代码的方法
2010/02/04 Javascript
jQuery hover 延时器实现代码
2011/03/12 Javascript
jQuery选择器的工作原理和优化分析
2011/07/25 Javascript
枚举的实现求得1-1000所有出现1的数字并计算出现1的个数
2013/09/10 Javascript
jquery将一个表单序列化为一个对象的方法
2013/12/02 Javascript
JavaScript中定义函数的三种方法
2015/03/12 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【一】
2016/05/10 Javascript
DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
2016/11/09 Javascript
原生js实现新闻列表展开/收起全文功能
2017/01/20 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
微信小程序时间轴实现方法示例
2019/01/14 Javascript
使用vue实现多规格选择实例(SKU)
2019/08/23 Javascript
JavaScript变量Dom对象的所有属性
2020/04/30 Javascript
手动实现vue2.0的双向数据绑定原理详解
2021/02/06 Vue.js
简单介绍Ruby中的CGI编程
2015/04/10 Python
Python实现进程同步和通信的方法
2018/01/02 Python
python 批量解压压缩文件的实例代码
2019/06/27 Python
用Python批量把文件复制到另一个文件夹的实现方法
2019/08/16 Python
python3实现单目标粒子群算法
2019/11/14 Python
用Python画小女孩放风筝的示例
2019/11/23 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
2020/01/09 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
美国电子元器件分销商:Newark element14
2018/01/13 全球购物
俄罗斯购买内衣网站:Trusiki
2020/08/22 全球购物
计算机专业毕业生推荐信
2013/11/25 职场文书
中国梦的演讲稿
2014/01/08 职场文书
顶撞领导检讨书
2014/01/29 职场文书
公司门卫的岗位职责
2014/02/19 职场文书
房屋买卖委托书格式范本格式
2014/10/13 职场文书
考察邀请函范文
2015/01/31 职场文书
HTML+CSS+JS实现图片的瀑布流布局的示例代码
2021/04/22 HTML / CSS
MySQL的存储过程和相关函数
2022/04/26 MySQL
Python如何快速找到多个字典中的公共键(key)
2022/04/29 Python