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 相关文章推荐
jQuery取得select选择的文本与值的示例
Dec 09 Javascript
Node.js实现在目录中查找某个字符串及所在文件
Sep 03 Javascript
JavaScript实现从数组中选出和等于固定值的n个数
Sep 03 Javascript
JS实现仿QQ效果的三级竖向菜单
Sep 25 Javascript
jquery ui dialog替代confirm实例分析
Jan 25 Javascript
Bootstrap 网格系统布局详解
Mar 19 Javascript
js表单序列化判断空值的实例
Sep 22 Javascript
JavaScript实现获取select下拉框中第一个值的方法
Feb 06 Javascript
webpack 打包压缩js和css的方法示例
Mar 20 Javascript
JavaScript this指向相关原理及实例解析
Jul 10 Javascript
比较node.js和Deno
Apr 27 Javascript
Vue elementUI表单嵌套表格并对每行进行校验详解
Feb 18 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
索尼SONY SRF-S83/84电路分析和打磨
2021/03/02 无线电
PHP获取栏目的所有子级和孙级栏目的ID号示例
2014/04/01 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
PHP 设计模式系列之 specification规格模式
2016/01/10 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
2016/03/22 PHP
JavaScript 数组循环引起的思考
2010/01/01 Javascript
修改jquery.lazyload.js实现页面延迟载入
2010/12/22 Javascript
jQuery1.6 类型判断实现代码
2011/09/01 Javascript
原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)
2013/06/24 Javascript
Javascript常用字符串判断函数代码分享
2014/12/08 Javascript
推荐10 款 SVG 动画的 JavaScript 库
2015/03/24 Javascript
jquery实现的Accordion折叠面板效果代码
2015/09/02 Javascript
JS实现兼容性较好的随屏滚动效果
2015/11/09 Javascript
js获取当前时间(昨天、今天、明天)
2016/11/23 Javascript
vue2.0数据双向绑定与表单bootstrap+vue组件
2017/02/27 Javascript
js实现移动端导航点击自动滑动效果
2017/07/18 Javascript
knockoutjs模板实现树形结构列表
2017/07/31 Javascript
layui 监听select选择 获取当前select的ID名称方法
2019/09/24 Javascript
Vue路由守卫之路由独享守卫
2019/09/25 Javascript
vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)
2019/12/29 Javascript
Python使用迭代器捕获Generator返回值的方法
2017/04/05 Python
Python基于列表模拟堆栈和队列功能示例
2018/01/05 Python
简单实现Python爬取网络图片
2018/04/01 Python
在PyCharm导航区中打开多个Project的关闭方法
2019/01/17 Python
Python3内置模块random随机方法小结
2019/07/13 Python
Win下PyInstaller 安装和使用教程
2019/12/25 Python
印度领先的眼镜电子商务网站:Lenskart
2019/12/16 全球购物
演讲稿怎么写
2014/01/07 职场文书
幼儿园小班家长寄语
2014/04/02 职场文书
合同和协议有什么区别?
2014/10/08 职场文书
2014初中数学教研组工作总结
2014/12/19 职场文书
高中生社会实践心得体会
2016/01/14 职场文书
2019职场实习报告该怎么写?
2019/07/01 职场文书
python基础学习之递归函数知识总结
2021/05/26 Python
详解MySql中InnoDB存储引擎中的各种锁
2022/02/12 MySQL
分享几种python 变量合并方法
2022/03/20 Python