【问题标题】:Error Handling in express on async functions does not work异步函数中 express 的错误处理不起作用
【发布时间】:2021-11-14 20:19:49
【问题描述】:

我一直在尝试使用 try 和 catch 以及创建一个单独的文件在 Express 中对异步函数实施错误处理,但是当我收到错误时 express 无法处理它,网站就会崩溃。

我已经在 app.get('/campgrounds/:id...

JS文件:

const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const Campground = require('./modules/campground');
const engine = require('ejs-mate');
const methodOverride = require('method-override');
const cities =  require('./seeds/cities')
const ExpressError = require('./utilities/ExpressError');
const catchAsync = require('./utilities/catchAsync');

mongoose.connect('mongodb://localhost:27017/yelpcamp');

const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", () => {
    console.log("Database connected");
});

const app = express();

app.engine('ejs', engine);
app.set('view engine','ejs');
app.set('views',path.join(__dirname,'views'));
app.use(express.urlencoded({extended:true}));
app.use(methodOverride('_method'));


app.get('/',(req,res)=>{
 res.redirect('/campgrounds');
})

app.get('/campgrounds',catchAsync(async (req,res)=>{
    const campgrounds = await Campground.find({});
    res.render('campgrounds/index',{campgrounds})
}))

app.get('/campgrounds/new',catchAsync(async (req,res)=>{
    const campgrounds = await Campground.find({});
    res.render('campgrounds/new',{ campgrounds })   
}))
app.post('/campgrounds',catchAsync(async(req,res, next)=>{
    const newCampground = new Campground(req.body);
    await newCampground.save();
    res.redirect(`campgrounds/${newCampground._id}`);
}))  
app.patch('/campgrounds/:id', catchAsync(async (req,res)=>{
    const {id}=req.params;
    const campground = await Campground.findByIdAndUpdate(id, req.body, {runValidators: true, new: true});
    res.redirect(`/campgrounds/${id}`)
}))

app.delete('/campgrounds/:id',catchAsync(async (req,res)=>{
    const { id } = req.params;
    await Campground.findByIdAndDelete(id);
    res.redirect('/campgrounds');
}))
app.get('/campgrounds/:id',catchAsync(async (req,res,next)=>{
    const { id } = req.params;
    const campground = await Campground.findById(id);
    res.render('campgrounds/details',{campground})
}))
app.get('/campgrounds/:id/edit',catchAsync(async(req,res)=>{
    const { id } = req.params;
    const campgrounds = await Campground.find({});
    const campground = await Campground.findById(id);
    res.render('campgrounds/edit',{campground, campgrounds});
}))
app.use((err,req,res,next)=>{
    res.send('Error here!');
})

app.listen(3000,()=>{
    console.log('Listening on port 3000')    
})

这是名为 catchAsync 的单独文件:

module.exports = func =>{
    return (req,res,next) =>{
        func(req,res,next).catch(next);
    }
}

【问题讨论】:

    标签: javascript node.js mongodb express asynchronous


    【解决方案1】:

    如果Mongoose 没有找到使用findById 的文档,则返回null。因此,在您的情况下,const campground = await Campground.findById(id); 不会引发错误/拒绝,而是将 null 作为 campground 传递给您的 ejs 模板,这可能会导致您描述的错误。

    如果你想实际抛出一个错误并强制调用你的错误处理程序,你可以从你的/find-handler 中抛出一个错误,例如

    app.get('/campgrounds/:id',catchAsync(async (req,res,next)=>{
        const { id } = req.params;
        const campground = await Campground.findById(id);
        if(!campground) {
          throw new Error("Campground not found");
        }
        res.render('campgrounds/details',{campground})
    }))
    

    【讨论】:

    • 感谢您的回答,您是对的。现在可以了。我想我必须对所有这些都这样做,如果我手动抛出错误,我还需要 catchAsync 吗?
    • 是的,但您可能想查看github.com/Automattic/mongoose/issues/3298
    • 好的,感谢您的宝贵时间!
    猜你喜欢
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 2018-07-13
    • 2011-03-03
    相关资源
    最近更新 更多