[英]Propper way of Error handling in a nodejs API server
我需要處理 node.js 上的 API 服務器中的錯誤。 我創建了一個錯誤處理模塊,它將錯誤(僅在開發模式下)發送到 JSON object 中的 API 客戶端,類似於:
{
"status": "fail",
"error": {
"statusCode": 404,
"status": "fail",
"isOperational": true
},
"message": "no valid register found. Please provide a valid register",
"stack": "Error: no valid register found. Please provide a valid register\n at /Users/myUser/ITstuff/smarthome-heating/controllers/modbusController.js:77:21\n at async /Users/myUser/ITstuff/smarthome-heating/controllers/modbusController.js:73:17"
}
現在我遇到的問題是,當 switch 語句中沒有 case 為真時,我需要在我的 API controller 的子模塊中創建一個新錯誤。
// this is the modbusHandler.setValue(doc, val, next) function
// 2) RUN PROGRAMMS
let checkVal;
switch (doc.register) {
case 0:
await client.writeCoil(doc.address + offset, !!val);
checkVal = await client.readCoils(doc.address + offset, 1);
break;
case 4:
await client.writeRegister(doc.address + offset, val);
checkVal = await client.readHoldingRegisters(doc.address + offset, 1);
break;
default:
throw new Error(
'no valid register found. Please provide a valid register'
);
}
這時候,我是這樣處理的:
// the function is wrapped in a try-catch statement
const val = await modbusHandler.setValue(doc, req.body.value, next).catch((err) => {
console.log('here it is');
return next(new AppError(err.message, 404));
});
res.status(200).json({
status: 'success',
data: {
val,
},
});
此解決方案實際上不起作用,我收到響應錯誤,因為 API controller 的 function 沒有返回。 這會導致第二個響應,這當然是不好的。
我現在的問題是:我怎樣才能以正確的方式解決這個問題?
自定義錯誤構造函數:
class AppError extends Error {
constructor(message, statusCode) {
// this is the official error message rom the error it self, this message will be in the response.json for the client
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = AppError;
自定義錯誤處理程序:
module.exports = (err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
if (process.env.NODE_ENV === 'development') {
sendErrDev(err, res);
} else if (process.env.NODE_ENV === 'production') {
sendErrProd(err, res);
}
};
const sendErrDev = (err, res) => {
res.status(err.statusCode).json({
status: err.status,
error: err,
message: err.message,
stack: err.stack,
});
};
而不是拋出錯誤,也許希望像這樣將它拋出到下一個,以便它可以由錯誤處理程序處理。
export const yourFunction = async (req, res, next) => {
.....
// throw the error to your route Error handler
return next(new AppError('no valid register found. Please provide a valid register', 400))
}
然后在所有路由聲明之后,您應該有一個看起來像的錯誤處理程序。
app.use(ErrorHandler);
//catchAsync
module.exports = fn => {
return (req, res, next) => {
fn(req, res, next).catch(next);
};
};
您將像這樣包裝您的路線。
route.get('/path/', catchAsync(yourFunction))
如果您創建了 catchAsync 中間件,則您的路由中根本不需要任何 Try/Catch,因為所有這些都將被扔給您的錯誤處理程序。
關於節點的小抱怨,甚至 javascript 都是關於錯誤處理的。 對於每個調用的 function 的 function 的 function 的 function ,那么你需要拋出錯誤的錯誤的錯誤。 你不斷冒泡“拋出錯誤”,然后它就會失控。
在您的 switch 語句中,我建議您返回 null。
然后你測試`if (;variable) return next(new AppError);
輔助函數的行為應該類似於輔助函數 function,它應該返回真/假/空/值,然后您在主 function 中確定是否應該拋出錯誤。
這樣你就可以集中你的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.