新建appError.js
可以获得自己设置的状态码和报错信息
class AppError extends Error {
constructor(message, status) {
super();
this.message = message;
this.status = status;
}
}
module.exports = AppError;
index.js:
- 导入appError:
const AppError = require('./AppError');
- 使用:
const verifyPassword = (req, res, next) => {
const { password } = req.query;
if (password === 'chickennugget') {
next();
}
throw new AppError('password required', 401);
// res.send("PASSWORD NEEDED!")
// throw new AppError('Password required!', 400)
}
app.get('/admin', (req, res) => {
throw new AppError('You are not an Admin!', 403)
})
//写在最后
//status = 500, message = 'Something Went Wrong' 为默认状态
app.use((err, req, res, next) => {
const { status = 500, message = 'Something Went Wrong' } = err;
res.status(status).send(message)
})
异步Error
因为是中间件,所以一定要有next,且如果出错,则return next(new AppError(‘Product Not Found’, 404));这样整个程序还是能正常运行
app.get('/products/:id',async (req, res, next) => {
const { id } = req.params;
const product = await Product.findById(id)
if (!product) {
return next(new AppError('Product Not Found', 404));
}
res.render('products/show', { product })
})
- 数据库(mongo)报错
app.post('/products', async (req, res, next) => {
try {
const newProduct = new Product(req.body);
await newProduct.save();
res.redirect(`/products/${newProduct._id}`)
} catch (e) {
next(e);
}
})
- Try Catch 可以捕获一切Error,所以不管是数据库还是js出错都只用Try Catch就行:
app.get('/products/:id',async (req, res, next) => {
try{
const { id } = req.params;
const product = await Product.findById(id)
if (!product) {
throw new AppError('Product Not Found', 404);
}
res.render('products/show', { product })
}catch(e){
next(e)
}
})
- 所以可以进行封装:
function wrapAsync(fn) {
return function (req, res, next) {
fn(req, res, next).catch(e => next(e))
}
}
app.post('/products', wrapAsync(async (req, res, next) => {
const newProduct = new Product(req.body);
await newProduct.save();
res.redirect(`/products/${newProduct._id}`)
}))
app.get('/products/:id', wrapAsync(async (req, res, next) => {
const { id } = req.params;
const product = await Product.findById(id)
if (!product) {
throw new AppError('Product Not Found', 404);
}
res.render('products/show', { product })
}))
app.use((err, req, res, next) => {
const { status = 500, message = 'Something went wrong' } = err;
res.status(status).send(message);
})
- Mongoose错误打印:
const handleValidationErr = err => {
console.dir(err);
//In a real app, we would do a lot more here...
return new AppError(`Validation Failed...${err.message}`, 400)
}
app.use((err, req, res, next) => {
console.log(err.name);
//We can single out particular types of Mongoose Errors:
if (err.name === 'ValidationError') err = handleValidationErr(err)
next(err);
})
app.use((err, req, res, next) => {
const { status = 500, message = 'Something went wrong' } = err;
res.status(status).send(message);
})