如何在快递中抛出 404 错误.js

How to throw a 404 error in express.js?

本文关键字:错误 js 快递      更新时间:2023-09-26

在应用程序中.js,我有

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

所以如果我请求一些不存在的网址,比如http://localhost/notfound,上面的代码将执行。

在像http://localhost/posts/:postId这样的存在网址中,我想在访问一些不存在的postId或删除postId时抛出404错误。

Posts.findOne({_id: req.params.id, deleted: false}).exec()
  .then(function(post) {
    if(!post) {
      // How to throw a 404 error, so code can jump to above 404 catch?
    }

在Express中,可以这么说,404不被归类为"错误" - 这背后的原因是404通常不是出现问题的迹象,只是服务器找不到任何东西。最好的办法是在路由处理程序中显式发送 404:

Posts.findOne({_id: req.params.id, deleted: false}).exec()
  .then(function(post) {
    if(!post) {
      res.status(404).send("Not found.");
    }

或者,如果这感觉像是太多重复的代码,你总是可以将该代码拉到一个函数中:

function notFound(res) {
    res.status(404).send("Not found.");
}
Posts.findOne({_id: req.params.id, deleted: false}).exec()
      .then(function(post) {
        if(!post) {
          notFound(res);
        }

我不建议在这种情况下使用中间件,因为我觉得它使代码不太清晰 - 404 是数据库代码未找到任何内容的直接结果,因此在路由处理程序中使用响应是有意义的。

我有相同的app.js结构,我在路由处理程序中以这种方式解决了这个问题:

router.get('/something/:postId', function(req, res, next){
    // ...
    if (!post){
        next();
        return;
    }
    res.send('Post exists!');  // display post somehow
});

next()函数将调用下一个中间件,即 error404 处理程序,如果它紧跟在应用程序中的路由之后.js。

您可以使用这个和路由器的末端。

app.use('/', my_router);
....
app.use('/', my_router);
app.use(function(req, res, next) {
        res.status(404).render('error/404.html');
    });

您可能正在寻找类似 https://github.com/expressjs/api-error-handler或者只是 https://github.com/jshttp/http-errors

尽管 404 页在这里写的 Express 中不被视为错误,但如果您确实像这样处理它们,它真的非常方便。例如,当您开发需要一致 JSON 输出的 API 时。以下代码应该可以帮助您:

定义一个帮助程序函数abort创建状态错误,这些错误可以在代码中轻松用于传递给next函数:

// Use the `statuses` package which is also a dependency of Express.
const status = require('statuses');
const abort = (code) => {
    const err = new Error(status[code]);
    const err.status = code;
    return err;
};

为 404 页面定义包罗万象的中间件,这些中间件应在堆栈底部定义(在添加所有路由之后)。这会将 404 作为错误转发:

app.use((req, res, next) => {
    next(abort(404));
});

最后,最终的错误处理程序现在将以 JSON 格式一致地发送所有错误:

app.use((err, req, res, next) => {
    
    if(!res.headersSent) {
        // You can define production mode here so that the stack trace will not be sent.
        const isProd = false;
        res.status(err.status || 500).json({
            error: err.toString(),
            ...(!isProd && {stack: err.stack.split(''n').map(i => i.trim())}),
        });
    }
    next(err);
});