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 相关文章推荐
javascript引用对象的方法
Jan 11 Javascript
JavaScript在for循环中绑定事件解决事件参数不同的情况
Jan 20 Javascript
js日期联动示例
May 02 Javascript
JavaScript实现动态创建CSS样式规则方案
Sep 06 Javascript
jQuery简单实现网页选项卡特效
Nov 24 Javascript
12306验证码破解思路分享
Mar 25 Javascript
js简单获取表单中单选按钮值的方法
Aug 23 Javascript
jquery 仿锚点跳转到页面指定位置的实例
Feb 14 Javascript
Vue中的v-cloak使用解读
Mar 27 Javascript
vue.js中npm安装教程图解
Apr 10 Javascript
jQuery实现鼠标移到某个对象时弹出显示层功能
Aug 23 jQuery
一文搞懂redux在react中的初步用法
Jun 09 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
解析在apache里面给php写虚拟目录的详细方法
2013/06/24 PHP
PHP的Yii框架中Model模型的学习教程
2016/03/29 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
JS中剪贴板兼容性、判断复制成功或失败
2021/03/09 Javascript
Ext JS添加子组件的误区探讨
2013/06/28 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
jquery.Ajax()方法调用Asp.Net后台的方法解析
2014/02/13 Javascript
一个简单的实现下拉框多选的插件可移植性比较好
2014/05/05 Javascript
轻松创建nodejs服务器(8):非阻塞是如何实现的
2014/12/18 NodeJs
javascript关于open.window子页面执行完成后刷新父页面的问题分析
2015/04/27 Javascript
jQuery鼠标经过方形图片切换成圆边效果代码分享
2015/08/20 Javascript
jQuery多级手风琴菜单实例讲解
2015/10/22 Javascript
Node.js的Koa框架上手及MySQL操作指南
2016/06/13 Javascript
js实现的光标位置工具函数示例
2016/10/03 Javascript
基于JavaScript实现熔岩灯效果导航菜单
2017/01/04 Javascript
js实现无缝滚动图
2017/02/22 Javascript
解决Vue编译时写在style中的路径问题
2017/09/21 Javascript
详解JavaScript中的六种错误类型
2017/09/21 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
jQuery中ajax获取数据赋值给页面的实例
2017/12/31 jQuery
jQuery+CSS实现的标签页效果示例【测试可用】
2018/08/14 jQuery
vue实现防抖的实例代码
2021/01/11 Vue.js
python smtplib模块发送SSL/TLS安全邮件实例
2015/04/08 Python
Python中强大的命令行库click入门教程
2016/12/26 Python
R vs. Python 数据分析中谁与争锋?
2017/10/18 Python
Python hashlib模块的使用示例
2020/10/09 Python
python中lower函数实现方法及用法讲解
2020/12/23 Python
使用HTML5原生对话框元素并轻松创建模态框组件
2019/03/06 HTML / CSS
Aerosoles爱柔仕官网:美国舒软女鞋品牌
2017/07/17 全球购物
政府采购方案
2014/06/12 职场文书
2014年党委工作总结
2014/11/22 职场文书
终止解除劳动合同证明书
2015/06/17 职场文书
2015年中秋放假通知范文
2015/08/18 职场文书
Python爬虫实战之爬取携程评论
2021/06/02 Python
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏
Python+pyaudio实现音频控制示例详解
2022/07/23 Python