【问题标题】:ExpressJS: Best way to separate routes and accepting params?ExpressJS:分离路线和接受参数的最佳方式?
【发布时间】:2022-01-07 22:44:36
【问题描述】:

我创建了一个 Express.js 系统,其中 /routes 文件夹中的文件充当经典路由(但每个路由一个文件)

例如:/routes/get/user.js 可以通过http://localhost:8080/user 访问(/get 是分隔方法,可以是/post/put...)

这是我的整个index.js 文件:https://pastebin.com/ALtSeHXc

但实际上,我的问题是我无法将参数传递到像 https://localhost:8080/user/random_id_here 这样的 url。

有了这个系统,我认为最好的办法是找到一种方法也可以在分离的文件上传递参数,但我不知道该怎么做......

这是我的一个分离文件的示例:

module.exports = class NameAPI {
    constructor(client) {
        this.client = client
    }

    async run(req, res) {
        // Code here
    }
}

也许你会有一个更好的系统,或者一个解决方案。谢谢。

【问题讨论】:

  • 为什么要使用文件系统作为要定义哪些路由的存储库?是否有什么神奇的东西让您在下次重新启动服务器时创建一个新文件神奇地创建一个新路由?为什么不在您的代码中构建一个指定所有内容的表格,您可以从表格中循环遍历表格构建路线。然后,您可以在表定义中添加任何您想要的内容,包括参数。
  • 如果您真的只想从文件 sytsem 中执行此操作,您可以将一些关于参数的内容作为属性存储在您的路由处理函数中。因此,您导入将处理路由的函数,然后访问该函数上指定参数之类的属性,以便您知道如何为该特定路由构建 Express 路由定义。请记住,函数是对象并且可以具有属性。
  • 注意:您的 _loadHttpMethode(method) 函数可以通过将每个 switch 语句的公共部分分解为采用一个参数(方法名称)的单个函数来大量减少其中的代码量。其他一切都只是复制代码。

标签: javascript node.js express web routes


【解决方案1】:

您可以从已有的模块对象中获取可选参数,因此每个模块都指定自己的参数。下面这个例子展示了在模块名称之后添加新参数,但如果需要,您可以扩展此功能以使其更丰富。

在一个简单的实现中,在你的加载器中,你可以改变这个:

   posts.forEach((post) => {
        const module = new (require(`./routes/post/${post}`))(this);
        this.api.post(`/${post}`, async (req, res) => await module.run(req, res))
    })

到这里:

   posts.forEach((post) => {
        const module = new (require(`./routes/post/${post}`))(this);
        const urlParams = module.params || "";
        this.api.post(`/${post}${urlParams}`, async (req, res) => module.run(req, res))
    });

因此,如果给定路由想要添加额外的 URL 参数 /:id,那么它只需将其导出的模块对象上的 .urlParams 属性定义为 `"/:id" 并且会自动包含在路由定义中。


附: _loadHttpMethode() 中的 switch 语句的每个分支中的大部分代码都是相同的。通过对一个通用函数和一个或两个传递给该函数的参数进行一些考虑,您可以消除开关的不同分支之间的所有复制代码,因此每个开关所做的只是调用一个函数并传递几个参数。

【讨论】:

  • 对于最后一部分,我这样做了:pastebin.com/7wZd55v0 可以更好吗? (这里没有添加你的代码,哎呀)
【解决方案2】:

如果您需要动态插入,我通常会设置我的快递来处理这种情况。这是个人代码,因此请进行必要的调整或观察行为! :)

WEBAPP.get('/room/:name', (req, res) => {
  // Check if URL ends with / (in my case I don't want that)
    if (req.url.endsWith('/')) return res.redirect('/');
  // Check if URL param "name" matches my regex ex. Username1920 or redirect them
    if (req.params.name.match(/^[a-zA-Z0-9]{3,24}$/) === null) return res.redirect('/');
  // render the room (sending EJS)
    res.render('room', {
        title: req.params.name.toUpperCase()
    });
});
/*

/*This example accepts one param and must follow my regex/rules*/

因此,如果您收到 /room/test12345,您的 req.params.name 将返回一个值。注意定义参数的冒号,所以你可以有 /:room/:user/:request 并且它会返回: req.params.room、req.params.user、req.params.request 全部定义! :)

【讨论】:

  • 嗯,问题是我需要将参数 1 逐 1 添加,不是吗?如果是,我想尽量避免这种情况,但如果这是唯一的解决方案,我会试试这个:)
  • 操作顺序,所以如果你想要 /:room 和 /:room/:user 和 /:room/:user/:id 这需要设置。否则只有 /:room/:user/:id 如果你通过 /newroomname/209593 你会出错,但 /newroomname/209593/20 会到达!!!!这可以是由您决定的 post/get/etc 命令。
  • Each : 代表一个参数,如果您希望链接 URL 中有多个参数,则必须实现。 :)
【解决方案3】:

如何在express API中分离路由和解析请求参数

您可以将每个模型的所有不同 API 方法放在一个单独的文件夹中,然后在您的主文件中解析 A​​PI 路由。

假设我们有一个名为 app.js 的主文件,您可以在子文件夹中组织您的 API 路由/端点。

文件夹结构:

├── app.js
└── routes
    └── api
        └── users.js

users.js 在文件夹 routes/api 在这种情况下包含您的用户端点的所有操作,并且您将其导入到您的 app.js 文件中。

根据下面定义的路由示例,您可以使用这些端点解析您的 express API:

GET YOUR_API:PORT/users           // fetch all users
GET YOUR_API:PORT/users/:userId   // fetch single user by id

app.js

// this is just a demo app.js, please adapt to your needs
const express = require("express");

// express app
const app = express();
app.use(express.json());

// api routes
// endpoint No. 1, this will create the endpoint /users
// and will enable you to use all methods defined in file users.js
app.use("/users", require("./routes/api/users"));

// add more endpoints, example endpoint No. 2
app.use("/ENDPOINT_NAME", require("./routes/api/FILE_NAME"));

// handle everything else you need to handle in your main file

// run server
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

在子文件夹 routes/api 中添加 api 路由文件,如下所示:

routes/api/users.js

const express = require('express');
const router = express.Router();

// here we only GET all users and user by id, 
// but you can add any endpoints required for your API.

// get all users
router.get('/', async (req, res) => {
    try {
        // do something to get all users
        const allUsers = // fetch all users, depends on how you want to do it
        return res.status(200).json(allUsers)
    } catch (err) {
        console.log(err)
        return res.status(400).json({ msg: 'Bad request.' })
    }
})

// get a specific user by Id from request parameters
router.get('/:userId', async (req, res) => {
    try {
        // user id from params
        const userId = req.params.userId
        // do something with this userId, for example look up in DB
        return res.status(200).json({userId: `Requested userId is ${userId}`})
        )        
    } catch (err) {
        console.log(err)
        return res.status(400).json({ msg: 'Bad request.' })
    }
})

// add more user endpoints here
// with router.post, router.put, router.delete, whatever you need to do

module.exports = router

【讨论】:

    猜你喜欢
    • 2012-10-16
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2013-06-29
    • 2012-09-01
    • 2018-12-23
    • 1970-01-01
    • 2021-11-10
    相关资源
    最近更新 更多