Express:为什么中间件对于独立路由器不能正常工作?

Express: why middlewares doesn't work properly for independent routers?

我有以下代码和 3 个独立的路由器

const Express = require("express")

const app = Express()

const usersRouter = Express.Router()
const productsRouter = Express.Router()
const storeRouter = Express.Router()

productsRouter.use((_, res, next) => {
  res.send("products fail")
  //next()
})

storeRouter.use((_, res, next) => {
  res.send("store fail")
  //next()
})

usersRouter.route("/users")
  .get((_, res) => res.send("users"))

productsRouter.route("/products")
  .get((_, res) => res.send("products"))

storeRouter.route("/store")
  .get((_, res) => res.send("store"))

app.use(usersRouter)
app.use(productsRouter)
app.use(storeRouter)

app.listen(80, () => console.log("running"))

但每次我请求 /store 路由时,它都会通过仅分配给它的 productRouter 中间件。

我无法理解这种行为。

这是为什么? 如何管理每个独立的中间件?

GET /store 200
products fail

预计

GET /store 200
store fail

当你这样做时:

app.use(productsRouter)

将所有请求发送到 productsRouter,因此它的中间件 运行 发送所有请求。所以,当你有这个:

productsRouter.use((_, res, next) => {
  res.send("products fail")
  //next()
});

每个请求都会 运行。

如果您希望路由器只看到某些请求,请在路径上注册路由器,这样路由器只会收到发往特定路径的请求。

app.use("/products", productsRouter)

然后从路由器的路由中删除路径本身,因为该路径已经被过滤了。

为了实现预期的行为,您必须对代码进行少量更改。

第一个: 采用这种方法,因为它可以让你保持所有东西干净和分离(如果你想为每个路由实现特定的中间件,这是至关重要的)。

usersRouter.
  .get("/", (req, res) => res.send("users"))

productsRouter.route
  .get("/", (req, res) => res.send("products"))

storeRouter.route("/store")
  .get("/", (req, res) => res.send("store"))

app.use("/users", usersRouter)
app.use("/products", productsRouter)
app.use("/store", storeRouter)

而不是这个

usersRouter.route("/users")
  .get((_, res) => res.send("users"))

productsRouter.route("/products")
  .get((_, res) => res.send("products"))

storeRouter.route("/store")
  .get((_, res) => res.send("store"))

app.use(usersRouter)
app.use(productsRouter)
app.use(storeRouter)

第二个: 取消注释中间件上的 next() 调用,在它们的回调中识别请求参数并将它们存储在变量中(不重要,但提高可读性)

const productsMiddleware = (req, res, next) => {
  res.send("products fail")
  next()
}

const storeMiddleware = (res, res, next) => {
  res.send("store fail")
  next()
}

第三名: 在路由之后和路由器上的实际控制器声明之前传递要应用于特定控制器的中间件。例如

usersRouter.
  .get("/", (req, res) => res.send("users"))

productsRouter.route
  .get("/", productsMiddleware, (req, res) => res.send("products"))

storeRouter.route("/store")
  .get("/", storeMiddleware, (req, res) => res.send("store"))

通过执行所有这些操作,您将得到仅适用于指定 route/controller.

的“独立中间件”