如何结合两个中间件并作为一个导出?

时间:2019-06-01 16:11:21

标签: node.js express middleware

我有一个实用程序文件,该文件基本上具有充当中间件的两个功能(一个用于检测用户位置,另一个用于获取用户设备详细信息)。现在,我想知道是否有可能将两个中间件组合为一个,以便可以与路由上的其他中间件一起使用。我还希望在需要时可以自由使用实用程序文件中的功能。

实用程序文件

const axios             = require("axios");
const requestIp         = require("request-ip");

const getDeviceLocation = async (req, res, next) => {
    try {
        // ToDO: Check if it works on production
        const clientIp  = requestIp.getClientIp(req);
        const ipToCheck = clientIp === "::1" || "127.0.0.1" ? "" : clientIp;

        const details = await axios.get("https://geoip-db.com/json/" + ipToCheck);

        // Attach returned results to the request body
        req.body.country    = details.data.country_name;
        req.body.state      = details.data.state;
        req.body.city       = details.data.city;

        // Run next middleware
        next();
    }
    catch(error) {
        return res.status(500).json({ message: "ERROR_OCCURRED" });
    }
};

const getDeviceClient = async (req, res, next) => {
    const userAgent = req.headers["user-agent"];

    console.log("Device UA: " + userAgent);
    next();
};

module.exports = { getDeviceLocation, getDeviceClient };

示例路线

app.post("/v1/register", [getDeviceLocation, getDeviceClient, Otp.verify], User.create);

app.post("/v1/auth/google", [getDeviceLocation, getDeviceClient, Auth.verifyGoogleIdToken], Auth.useGoogle);  

我想将getDeviceLocationgetDeviceClient组合成一个说getDeviceInfo,但可以自由地在任何需要时单独使用getDeviceLocationgetDeviceClient路线。

5 个答案:

答案 0 :(得分:3)

Express 允许您declare middleware in an array,因此您可以简单地定义要组合的中间件数组:

const getDeviceLocation = async (req, res, next) => {
...
};

const getDeviceClient = async (req, res, next) => {
...
};

const getDeviceInfo = [getDeviceLocation, getDeviceClient];

module.exports = { getDeviceLocation, getDeviceClient, getDeviceInfo };

然后,您可以随心所欲地使用一种或两种中间件的任意组合:

app.use('/foo', getDeviceLocation, () => {});
app.use('/bar', getDeviceClient, () => {});
app.use('/baz', getDeviceInfo, () => {});

答案 1 :(得分:1)

如果您想避免出现回调地狱,可以使用以下代码:

import sys
stdout = sys.stdout

# some functions that mess up sys.stdout

sys.stdout = stdout

答案 2 :(得分:0)

使用connect nodemodule可以组合中间件并为其提供一个新的端点。在此处引用示例代码https://blog.budiharso.info/2015/07/28/Combine-multiple-express-middleware/

答案 3 :(得分:0)

在您的情况下,您可以使用类似以下的简单方法

const getDeviceInfo = async (req, res, next) => {
    await getDeviceClient(req, res, async () => {
        await getDeviceLocation(req, res, next)
    })
}

但是您可能需要处理错误情况。

答案 4 :(得分:0)

它很简单,不需要安装任何东西。只需使用:

const {Router} = require('express')

const combinedMiddleware = Router().use([middleware1, middleware2, middleware3])

现在您可以在必要时使用组合中间件。例如:

app.get('/some-route', (req, res, next) => {
  req.query.someParam === 'someValue'
    ? combinedMiddleware1(req, res, next)
    : combinedMiddleware2(req, res, next)
})