繁体   English   中英

如何在每条路线 function 中自动化 next() 调用? (express.js)

[英]How to automate next() call in every route function? (express.js)

您好我面临的问题是我需要在我的数据库中记录每个传入的请求和相关的响应。 我当前的解决方案如下所示:

./routes/customer.js

router.get('/', async (req, res, next) => {
    req.allCustomers = await fetchAllCustomers();
    res.status(200).send(req.allCustomers);
    next();  // <- this is my personal problem
});

./middleware/logging.js

module.exports = function (req, res, next) {
    db.query(
        `INSERT INTO logging SET ?`, 
         { 
            request: JSON.stringify([req.body, req.params]), 
            response: JSON.stringify(req.response) 
         }
    );
}

路线声明

module.exports = function(app) {
    app.use(express.json());
    app.use('/api/customers', customers); // <- ROUTE ./routes/customer.js
    app.use(logging); // <- MIDDLEWARE ./middleware/logging.js
}

我已经在我的第一段代码中提到了我的问题。 在每条路线中手动调用next()确实是重复的,我想避免这种情况。 我已经尝试在所有路由之前加载中间件,在中间件 function 中调用next()并在之后执行我的数据库查询,但由于异步功能,我此时没有响应。

有什么办法可以处理这种情况,还是我需要在每条路线 function 的末尾继续调用next()

如果您不想从路由中调用next() ,则不能让中间件在它们之后运行。 它需要放在前面。 但是你能在路由之前运行的中间件中得到响应吗? 答案是肯定的!

这可能有点老套,但由于您的路线使用res.send() ,您可以利用它来发挥自己的优势。 通过在你的路由之前运行,你的中间件可以劫持res.send function,让它做其他事情。

./routes/customer.js

router.get('/', async (req, res, next) => {
    req.allCustomers = await fetchAllCustomers();
    res.send(req.allCustomers); // We'll hijack this
});

./middleware/logging.js

module.exports = function (shouldBeLoggedFunc) {
  return function (req, res, next) {
    if (shouldBeLoggedFunc(req)) {
      // Store the original send method
      const _send = res.send;
      // Override it
      res.send = function (body) {
        // Reset it
        res.send = _send;
        // Actually send the response
        res.send(body);
        // Log it (console.log for the demo)
        console.log(`INSERT INTO logging SET ?`, {
          request: JSON.stringify([req.body, req.params]),
          response: JSON.stringify(body)
        });
      };
    }
    next();
  };
};

路线声明

function shouldBeLogged(req) {
  // Here, check the route and method and decide whether you want to log it
  console.log(req.method, req.path); // e.g. GET /api/customers
  return true;
}

module.exports = function(app) {
    app.use(express.json());
    app.use(logging(shouldBeLogged)); // <- Place this before your routes
    app.use('/api/customers', customers);
};

当您像您已经使用的那样使用 express.Router class 然后使用此代码时

 app.use('/api/customers', customers);

您不必在 router.get 中的回调 function 中编写“next()”。

有一个例子在app目录下创建一个名为birds.js的路由文件,内容如下:

 var express = require('express') var router = express.Router() // middleware that is specific to this router router.use(function timeLog (req, res, next) { console.log('Time: ', Date.now()) next() }) // define the home page route router.get('/', function (req, res) { res.send('Birds home page') }) // define the about route router.get('/about', function (req, res) { res.send('About birds') }) module.exports = router

然后,在应用程序中加载路由器模块:

 var birds = require('./birds') //... app.use('/birds', birds)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM