กรณีการใช้งานของฉันกำลังส่งข้อความแสดงข้อผิดพลาด JSON ที่กำหนดเองเนื่องจากฉันใช้ Express เพื่อเปิดใช้งาน REST API ฉันคิดว่านี่เป็นสถานการณ์ที่พบได้บ่อยดังนั้นจะเน้นที่คำตอบของฉัน
เวอร์ชั่นสั้น:
การจัดการข้อผิดพลาดด่วน
กำหนดมิดเดิลแวร์จัดการข้อผิดพลาดเหมือนกับมิดเดิลแวร์อื่น ๆ ยกเว้นมีอาร์กิวเมนต์สี่อาร์กิวเมนต์แทนที่จะเป็นสามโดยเฉพาะด้วยลายเซ็น (err, req, res, next) ... คุณกำหนดมิดเดิลแวร์จัดการข้อผิดพลาดเป็นอันดับสุดท้ายหลังจาก app.use () อื่นและกำหนดเส้นทางการโทร
app.use(function(err, req, res, next) {
if (err instanceof JSONError) {
res.status(err.status).json({
status: err.status,
message: err.message
});
} else {
next(err);
}
});
เพิ่มข้อผิดพลาดจากจุดใดก็ได้ในโค้ดโดยทำ:
var JSONError = require('./JSONError');
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);
เวอร์ชันยาว
วิธีที่ยอมรับได้ในการโยนข้อผิดพลาดคือ:
var err = new Error("Uh oh! Can't find something");
err.status = 404;
next(err)
โดยค่าเริ่มต้น Express จะจัดการสิ่งนี้โดยการบรรจุเป็น HTTP Response ด้วยรหัส 404 และเนื้อความประกอบด้วยสตริงข้อความที่ต่อท้ายด้วย stack trace
สิ่งนี้ไม่ได้ผลสำหรับฉันเมื่อฉันใช้ Express เป็นเซิร์ฟเวอร์ REST ฉันต้องการให้ส่งข้อผิดพลาดกลับเป็น JSON ไม่ใช่ HTML ฉันไม่ต้องการให้การติดตามสแต็กของฉันย้ายออกไปยังลูกค้าของฉันอย่างแน่นอน
ฉันสามารถส่ง JSON เป็นการตอบกลับโดยใช้req.json()
เช่น. บางอย่างเช่นreq.json({ status: 404, message: 'Uh oh! Can't find something'})
. อีกทางเลือกหนึ่งคือฉันสามารถตั้งรหัสสถานะโดยใช้req.status()
. การรวมสอง:
req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
การทำงานนี้เหมือนมีเสน่ห์ ที่กล่าวว่าฉันพบว่ามันค่อนข้างเทอะทะพิมพ์ทุกครั้งที่ผมมีข้อผิดพลาดและรหัสจะไม่-ตนเอง documenting เหมือนเราnext(err)
เป็น ดูเหมือนมากเกินไปกับวิธีการส่ง JSON การตอบกลับปกติ (เช่นถูกต้อง) นอกจากนี้ข้อผิดพลาดใด ๆ ที่เกิดจากวิธีการยอมรับยังคงส่งผลให้เอาต์พุต HTML
นี่คือที่มาของมิดเดิลแวร์การจัดการข้อผิดพลาดของ Express ในฐานะส่วนหนึ่งของเส้นทางของฉันฉันกำหนด:
app.use(function(err, req, res, next) {
console.log('Someone tried to throw an error response');
});
ฉันยังมีข้อผิดพลาดคลาสย่อยในคลาส JSONError ที่กำหนดเอง:
JSONError = function (status, message) {
Error.prototype.constructor.call(this, status + ': ' + message);
this.status = status;
this.message = message;
};
JSONError.prototype = Object.create(Error);
JSONError.prototype.constructor = JSONError;
ตอนนี้เมื่อฉันต้องการโยนข้อผิดพลาดในรหัสฉันทำ:
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);
กลับไปที่ข้อผิดพลาดที่กำหนดเองในการจัดการมิดเดิลแวร์ฉันแก้ไขเป็น:
app.use(function(err, req, res, next) {
if (err instanceof JSONError) {
res.status(err.status).json({
status: err.status,
message: err.message
});
} else {
next(err);
}
}
Subclassing Error ลงใน JSONError เป็นสิ่งสำคัญเนื่องจากฉันสงสัยว่า Express จะinstanceof Error
ตรวจสอบพารามิเตอร์แรกที่ส่งไปยัง a next()
เพื่อตรวจสอบว่าต้องเรียกตัวจัดการปกติหรือตัวจัดการข้อผิดพลาด ฉันสามารถลบการinstanceof JSONError
ตรวจสอบและทำการแก้ไขเล็กน้อยเพื่อให้แน่ใจว่ามีข้อผิดพลาดที่ไม่คาดคิด (เช่นข้อขัดข้อง) และส่งคืนการตอบสนอง JSON ด้วย