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 相关文章推荐
js动态加载以及确定加载完成的代码
Jul 31 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
Aug 11 Javascript
cookie中的path与domain属性详解
Dec 18 Javascript
JavaScript设计模式之代理模式介绍
Dec 28 Javascript
JS使用ajax方法获取指定url的head信息中指定字段值的方法
Mar 24 Javascript
javascript实现控制浏览器全屏
Mar 30 Javascript
JavaScript类继承及实例化的方法
Jul 25 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 Javascript
JSON在Javascript中的使用(eval和JSON.parse的区别)详细解析
Sep 05 Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
Sep 10 Javascript
vue.js实现图书管理功能
Sep 24 Javascript
关于JavaScript回调函数的深入理解
Jun 27 Javascript
详解如何在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中一个有意思的日期逻辑处理
2012/03/25 PHP
Thinkphp中import的几个用法详细介绍
2014/07/02 PHP
PHP自毁程序(慎用)
2015/07/09 PHP
深入理解PHP中的empty和isset函数
2016/05/26 PHP
php使用CutyCapt实现网页截图保存的方法
2016/10/03 PHP
php-beanstalkd消息队列类实例分享
2017/07/19 PHP
破解Session cookie的方法
2006/07/28 Javascript
mapper--图片热点区域高亮组件官方站点
2007/12/22 Javascript
JavaScript CSS修改学习第五章 给“上传”添加样式
2010/02/19 Javascript
JQuery 动态扩展对象之另类视角
2010/05/25 Javascript
jquery中对于批量deferred的处理方法
2014/01/22 Javascript
ExtJS4如何自动生成控制grid的列显示、隐藏的checkbox
2014/05/02 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
2016/01/14 Javascript
php main 与 iframe 相互通讯类(js+php同域/跨域)
2017/09/14 Javascript
Vue2.0设置全局样式(less/sass和css)
2017/11/18 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
2018/08/20 Javascript
详解vue-router传参的两种方式
2018/09/10 Javascript
JavaScript Dom 绑定事件操作实例详解
2019/10/02 Javascript
vue和小程序项目中使用iconfont的方法
2020/05/19 Javascript
JavaScript 实现轮播图特效的示例
2020/11/05 Javascript
Vue实现购物车基本功能
2020/11/08 Javascript
[01:52]深扒TI7聊天轮盘语音出处7
2017/05/11 DOTA
Python编程判断一个正整数是否为素数的方法
2017/04/14 Python
Django 如何获取前端发送的头文件详解(推荐)
2017/08/15 Python
Python简单读取json文件功能示例
2017/11/30 Python
Python实现的朴素贝叶斯分类器示例
2018/01/06 Python
Python实现去除列表中重复元素的方法小结【4种方法】
2018/04/27 Python
Django Model中字段(field)的各种选项说明
2020/05/19 Python
解决python 执行sql语句时所传参数含有单引号的问题
2020/06/06 Python
html5 video全屏播放/自动播放的实现示例
2020/08/06 HTML / CSS
大学生最常用的自我评价
2013/12/07 职场文书
服务之星事迹材料
2014/05/03 职场文书
政府绩效管理实施方案
2014/05/04 职场文书
2016年学习雷锋精神广播稿
2015/12/17 职场文书
Django migrate报错的解决方案
2021/05/20 Python
MySQL 四种连接和多表查询详解
2021/07/16 MySQL