【问题标题】:Express trigger not found route for each routeExpress trigger not found route for each route
【发布时间】:2020-12-06 22:40:10
【问题描述】:

我正在使用这样的模式:

app = express();
router = express.Router();

router.use((req, res, next) => {
  console.log("my middleware before");
  next();
});

router.get('/foo', (req, res, next) => {
  console.log("My route");
  res.send("<h1>Hello</h1>")
  next();
});

router.use((req, res, next) => {
  console.log("my middleware after");
});

app.use("/", router);

app.get("*", (req, res, next) => {
  console.log("page not found");
  throw new Error("Not Found");
});

app.use((err, req, res, next) => {
  console.log("Error occure");
  res.send("<h1>Error</h1>");
});

app.listen(3000);

当我请求“/foo”时,我想拥有

> my middleware before
> My route
> my middleware after
<h1>Hello</h1>

当我提出其他要求时:

> page not found
> Error occure
<h1>Error</h1>

但是在每种情况下都会执行找不到页面的路由,即使路由'/foo'已经完成。 我怎样才能让它工作?

【问题讨论】:

标签: node.js express


【解决方案1】:

这样做

app = express();
router = express.Router();

router.use((req, res, next) => {
  console.log("my middleware before");
  next();
});

router.get('/foo', (req, res, next) => {
  // use locals to record the fact we have a match
  res.locals.hasMatch = true
  console.log("My route");
  res.send("<h1>Hello</h1>")
  next();
});

router.use((req, res, next) => {
  console.log("my middleware after");
});

app.use("/", router);

app.get("*", (req, res, next) => {
  console.log("page not found");
  throw new Error("Not Found");
});

app.use((err, req, res, next) => {
  // check locals to see if we have a match
  if (!res.locals.hasMatch) {
    console.log("Error occure");
    res.send("<h1>Error</h1>");
  }
});

app.listen(3000);

【讨论】:

  • 这不会像 OP 要求的那样触发“我的中间件”。
  • 啊错过了,你
【解决方案2】:

当我运行你的代码时,我没有得到你显示的输出,所以关于你的真实代码的某些东西显然与你在问题中显示的不同。

我确实得到了一个稍微令人困惑的输出,这是因为浏览器同时发送了/foo 请求和/favicon.ico 请求。当我运行它时,/foo 请求会生成所需的输出。 /favicon.ico 请求生成一些中间件输出,然后卡在路由器中。

如果您通过将其添加为第一条路由来过滤掉 /favicon.ico 路由(以免混淆):

app.get("/favicon.ico", (req, res) => {
    res.sendStatus(404);
});

然后,当我请求 /foo 时,我在服务器日志中得到了这个输出:

my middleware before
My route
my middleware after

这正是你所要求的。


然而,这有一个普遍的问题:

router.use((req, res, next) => {
    console.log("my middleware after");
});

因为它会捕获并挂起任何尚未发送响应的合法请求。除非您仅在已发送响应的情况下不调用 next(),否则您无法真正以这种方式编写代码。

作为一个小技巧,你可以这样做:

router.use((req, res, next) => {
    console.log("my middleware after");

    // if response hasn't yet been sent, continue routing
    if (!res.headersSent) {
        next();
    }
});

但是,可能有更好的方法来解决您实际尝试解决的任何问题。如果将来您描述的是您的真正问题,而不是您的解决方案中存在的问题,那么您允许人们为您的实际问题提供更广泛的解决方案,包括您甚至没有想过尝试的事情。由于您的问题是现在写的,我们被困在您遵循的解决方案路径上,不知道最初的问题是什么。也就是说,顺便说一下,称为XY Problem。

【讨论】:

    【解决方案3】:

    您可以利用中间件,甚至可以嵌套它们。

    你可以这样实现:

    中间件

    const before = (req, res, next) => {
      console.log("my middleware before");
      next();                                    // Supply next() so that it will proceed to the next call, 
                                                 // in our case, since this is supplied inside the router /foo, after this runs, it will proceed to the next middleware
    };
    
    const after = (req, res, next) => {
      console.log("my middleware after");
    };
    

    路线

    // Supply "before" middleware on 2nd argument to run it first when this route is called
    router.get('/foo', before, (req, res, next) => {
      console.log("My route");              
      res.send("<h1>Hello</h1>");
    
      next();                               // Call next() to proceed to the next middleware, or in "after" middleware
    }, after);                              // Supply the "after" middleware
    

    一旦运行,它将继续执行所需的结果序列:

    > my middleware before
    > My route
    > my middleware after               
    

    不匹配的路由处理程序

    不是这个

    app.get("*", (req, res, next) => {
      console.log("page not found");
      throw new Error("Not Found");
    });
    

    你可以像这样实现它,这是在你的app.use("/", router);之后——这将处理你不匹配的路由:

    来源:

    app.use((req, res, next) => {
      console.log("page not found");
      res.json({ error: 'Page not Found' })      
    });
    

    【讨论】:

    • 感谢您的回复,但这不是我想要的,因为中间件不会在未找到的页面上执行。而且我将无法使用找不到路由器的特定页面和我的应用程序的通用页面。我发布了一个带有更好示例代码的新问题。对不起,这是在足够的测试之前发布的。 stackoverflow.com/questions/65872351/…
    猜你喜欢
    • 2019-10-05
    • 2021-05-24
    • 1970-01-01
    • 2021-12-30
    • 2019-08-20
    • 2020-03-22
    • 2020-04-12
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多