node錯(cuò)誤處理與日志記錄的實(shí)現(xiàn)
node項(xiàng)目中的錯(cuò)誤處理
node中Error對(duì)象的使用
使用captureStackTrace方法加入自帶的錯(cuò)誤信息
// Error對(duì)象自帶的屬性
Error.captureStackTrace
// 如何使用captureStackTrace
var obj = {
message: 'something is wrong'
}
Error.captureStackTrace(obj)
throw obj // 此時(shí)會(huì)拋出obj對(duì)象的message內(nèi)信息
使用try catch捕獲錯(cuò)誤
直接把代碼寫在try catch中即可捕獲錯(cuò)誤信息
try{
throw new Error('oh no')
}catch(e){
console.log(e)
}
在異步代碼中,直接try catch是無(wú)法捕獲錯(cuò)誤信息的,可以使用如下方法
function foo(params, cb){
const error = new Error('something is wrong')
if(error) cb(error)
}
以上使用callback方式來(lái)做錯(cuò)誤處理比較容易麻煩,容易出錯(cuò),現(xiàn)在node已經(jīng)支持async await所以盡量使用它們準(zhǔn)沒(méi)錯(cuò)
async function foo(){
try{
await bar()
}catch(e){
console.log(e)
}
}
async function bar(){
throw new Error('async function got wrong)
}
foo()
基本錯(cuò)誤類型
在項(xiàng)目會(huì)有多個(gè)地方對(duì)錯(cuò)誤信息進(jìn)行處理,所以先寫一個(gè)基本錯(cuò)誤類型,方便使用
// 基本錯(cuò)誤類型
class HttpBaseError extends Error {
constructor(httpStatusCode, httpMsg, errCode, msg) {
super(`HTTP ERROR: ${msg}`);
this.httpStatusCode = httpStatusCode;
this.httpMsg = httpMsg;
this.errCode = errCode;
}
}
try {
// 直接拋出定義好的錯(cuò)誤即可
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);
}
特定錯(cuò)誤類型
除了基本類型,不同情況下會(huì)有不同錯(cuò)誤信息,需要用一個(gè)特定的錯(cuò)誤類型來(lái)處理特定的錯(cuò)誤信息
// 一個(gè)參數(shù)錯(cuò)誤類型
const ERROR_CODE = 40000 // 錯(cuò)誤碼
class HttpRequestParamError extends HttpBaseError {
constructor(paramName, desc, msg) {
super(200, desc, ERROR_CODE, `${paramName} wrong: ${msg}`)
}
}
這樣,在參數(shù)錯(cuò)誤的地方就能非常方便的調(diào)用這個(gè)錯(cuò)誤類型來(lái)返回錯(cuò)誤
拋錯(cuò)的邏輯
錯(cuò)誤處理中,model,controller中的錯(cuò)誤,有些是不能直接返回給用戶的,應(yīng)該只返回給model或controller的調(diào)用者。
使用錯(cuò)誤處理
正常接口,controller,model的錯(cuò)誤,使用設(shè)定好的錯(cuò)誤類型進(jìn)行處理,例如前面寫的HttpRequestParamError,在所有所有路由的最后,需要使用一個(gè)error handler來(lái)對(duì)所有的錯(cuò)誤進(jìn)行集中處理
// error handler
function handler(options) {
return function (err, req, res, next) {
if (err instanceof HttpRequestParamError) { // 這里對(duì)不同的錯(cuò)誤做不同的處理
console.log('http request error')
res.statusCode = err.httpStatusCode
res.json({
code: err.errCode,
msg: err.httpMsg
})
} else {
// 設(shè)定之外的錯(cuò)誤,把管理權(quán)向外移交
next(err)
}
}
}
除了可預(yù)知的錯(cuò)誤,還有未知的類型的錯(cuò)誤,此時(shí)需要一個(gè)unknow error handler進(jìn)行剩余錯(cuò)誤的處理
function unKnowErrorHandler(options) {
return function (err, req, res, next) {
console.log(err)
res.json({
code: 99999,
msg: 'unKnow error'
})
}
}
node中的日志
平時(shí)使用console來(lái)debug是沒(méi)有問(wèn)題的,但是在線上環(huán)境,我們并不能有效的看到console,使用日志系統(tǒng)可以更好的方便線上的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' // 設(shè)置log的類型
}),
// 第二個(gè)logger,記錄error級(jí)別的log
new winston.transports.File({
name: 'error_logger',
filename: 'logs/error.log',
level: 'error'
})
]
});
// error級(jí)別比info要高,error.log文件只會(huì)記錄error日志
logger.error('first error log with winston')
// info文件內(nèi)會(huì)記錄info級(jí)別的log和比info級(jí)別高的log,比如error
logger.info('first info log with winston')
日志滾動(dòng)(log rotation)
在產(chǎn)生大量數(shù)據(jù)的應(yīng)用當(dāng)中,日志的輸出是大量的,這是就需要對(duì)日志進(jìn)行拆分處理,例如按照每天的頻率來(lái)分別記錄日志。
winston并不自帶log rotation,需要引入winston-daily-rotate-file庫(kù)
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!');
運(yùn)行日志文件,此時(shí)在logs目錄下就生成了今天的日志
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于nodejs使用express創(chuàng)建web服務(wù)器的操作步驟
express實(shí)際上是對(duì)nodejs內(nèi)置http進(jìn)行封裝后的第三方包,其中提供了快捷創(chuàng)建web服務(wù)器以及處理請(qǐng)求路由的方法,使我們可以更加方便快捷的實(shí)現(xiàn)一個(gè)web服務(wù)器項(xiàng)目,本文件給大家詳細(xì)介紹基于nodejs使用express?創(chuàng)建web服務(wù)器的操作步驟2023-07-07
nodejs控制臺(tái)打印高亮代碼的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于nodejs控制臺(tái)打印高亮代碼的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
Node解決簡(jiǎn)單重復(fù)問(wèn)題系列之Excel內(nèi)容的獲取
這篇文章主要給大家介紹了關(guān)于利用Node解決簡(jiǎn)單重復(fù)問(wèn)題系列之Excel內(nèi)容獲取的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧。2018-01-01
node+express實(shí)現(xiàn)分頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了node+express實(shí)現(xiàn)分頁(yè)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
express如何解決ajax跨域訪問(wèn)session失效問(wèn)題詳解
這篇文章主要給大家介紹了關(guān)于express如何解決ajax跨域訪問(wèn)session失效問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
初識(shí)NodeJS服務(wù)端開發(fā)入門(Express+MySQL)
本篇文章主要介紹了初識(shí)NodeJS服務(wù)端開發(fā)入門(Express+MySQL),可以對(duì)數(shù)據(jù)庫(kù)中的一張表進(jìn)行簡(jiǎn)單的CRUD操作,有興趣的可以了解一下。2017-04-04
HTTP JSON接口模擬工具Interfake快速入門教程
這篇文章主要為大家介紹了HTTP JSON接口模擬工具Interfake快速入門教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
nodejs構(gòu)建本地web測(cè)試服務(wù)器 如何解決訪問(wèn)靜態(tài)資源問(wèn)題
這篇文章主要為大家詳細(xì)介紹了nodejs構(gòu)建本地web測(cè)試服務(wù)器,教大家如何解決訪問(wèn)靜態(tài)資源問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07

