【问题标题】:Is an API and Router two separate things?API 和路由器是两个不同的东西吗?
【发布时间】:2021-06-29 13:34:21
【问题描述】:

我有一个带有 Express.js 应用程序的 Node.js。我有这样的文件夹:

src
   /models
   /router
   /store
   /api/v1
  index.js

我的router 文件夹有一个名为index.router.js 的文件,其中包含我的应用程序的路由,例如:

import UserAPI from '../api/v1/user.api.js'
expressRouter.post('/register', function async function (req, res)  {

         await UserAPI.registerUser({
         EMail: req.body.EMail,
         Password: req.body.Password,
         Name: req.body.Name
});

上面是一个路由到一个API,所以它进入了我的index.router.js文件。为了在这个端点上执行 API 操作,我为 API 功能创建了另一个名为 user.api.js 的文件,它包含以下内容:

async function registerUser({EMail, Password, Name}) {
  // Import method from model file and perform DB action
});

随着应用程序的增长,我开始怀疑我是否让它变得过于复杂,并使用user.api.js 的单独文件创建了一个不必要的层,该文件可能被重构为index.router.js 的一部分。

我不明白的是,为了可扩展性而构建 API 的文件的标准做法是什么?API 端点应该位于 api/v1api/v2 的单独文件/文件夹中,还是应该是 @987654332 的一部分@?

拥有单独的api 文件的好处之一是可重复使用性。因为它只包含函数而没有路由,所以可以在许多不同的路由器文件中重复使用这些函数。

【问题讨论】:

  • One thing that could be advantagous of having separate api files is resuability. Because it only contains functions and no routing, the functions could be reused across many different router files.一针见血,但不仅仅是单独的 HTTP 路由,您还可以重用这些相同的函数来创建其他 API(基于电子邮件、基于 CLI、基于串行等)。跨度>

标签: javascript node.js api express


【解决方案1】:

您基本上重新发明了MVC 设计模式。

这并不过分复杂。这被认为是良好的做法并受到鼓励。

C

传统上,您所说的路由器通常称为 C控制器。控制器的工作只是处理路由、处理参数解析(请求正文、查询参数、用户是否登录等),有时还处理验证。这正是 Express 的设计初衷。 Express 允许将身份验证和验证等控制器功能重构到中间件中。

注意:有时您会在互联网上看到人们将控制器和路由分开的教程。我个人的建议是不要这样做。快速路由被设计成非常适合编写控制器。关于将它们分开的ONLY 原因是,如果您有两个不同的 URL 执行完全相同的操作。在我看来,最好通过重定向来处理。

M

传统上,您将 API 称为 Model。模型是您学习编程的对象或数据结构的传统集合。模型是执行应用程序逻辑的东西。通常,实现模型的类或模块没有任何标签。例如,用户模型不会被称为UserAPIUserModel,而只是称为User。但是,您对事物的命名只是一种约定。坚持对你有意义的事情。

V

MVC 的最后一部分是 View。在 Express 中,视图只是 res.json()res.render() 及其关联的 HTML 模板。这部分 99% 已经由 Express 开发人员编写——您只需要告诉视图函数将什么发送到前端。

你的架构不错

将模型(API)与控制器(路由器)分开是有充分理由的。首先是它可以让你解决你的问题,而不会用参数解析逻辑污染你的核心逻辑。您的模型不需要担心用户登录的天气或数据是如何传递给它的。

其次,它允许您在 Express 之外使用模型 (API) 逻辑。最明显的用途是单元测试。这允许您在没有代码的 Web 部分的情况下对核心逻辑进行单元测试。我通常还编写实用程序脚本,可用于创建新用户、转储用户数据、生成身份验证令牌,以便我可以将其与 Postman 一起使用等。

例如,您可以创建如下脚本:

#! /usr/bin/env node
// register-user.js

import UserAPI from '../api/v1/user.api.js'

UserAPI.registerUser({
    EMail: process.argv[2],
    Password: process.argv[4],
    Name: process.argv[3]
})
.then(x => {console.log(x); process.exit()})
.catch(console.error);

然后您可以在命令行上执行以创建新用户而无需运行服务器:

$ ./register-user.js myemail@address.com 'My Name' 123456

看起来您的软件已经按照 MVC 进行了结构化。保持这种方式。这将使维护和修改软件变得更加容易。

【讨论】:

  • 在我的一些小型项目中,我实际上将实用程序脚本用作临时测试,而不是编写适当的单元测试代码。它不如可重复的单元测试,但它可以让你“玩”你的应用程序逻辑来验证功能
  • 我松了口气,也很喜欢剧本的想法。感谢您投票的答案
【解决方案2】:

API 和路由器是两个不同的东西,甚至来自不同的世界。

大多数应用程序由两个基本构建块组成,即 UI 和 API。 UI 应该是为人类服务的,而 API 应该是为机器服务的。您可以拥有 0-n 个 UI 和 0-n 个 API。没有规则。

例如 UI,您可能有一个面向普通访问者的网页、面向付费访问者或购买您产品的用户的应用程序以及面向管理员的应用程序。这是三个独立的 UI。如果一个发生故障,其他人正在工作。

另一个例子是 API。这些 UI 中的每一个都可以有单独的 API。也可以有用于第三方的 API 或您自己系统的其他微服务。同样,如果一个 API 不起作用,它不会影响其他 API。

Router 是 URL 控制的设计模式。或者,如果您愿意,也可以是设计模式的特定实现。

虽然 UI 和 API可能都需要 URL 控制,但在应用程序系统的两个部分都可以使用相同的模式。但这并不意味着它应该在同一个文件夹中。构建块的东西应该在单独的文件夹中。路由器与模型不同,它不是您在构建块之间共享的常见事物。

你在这里展示的文件夹结构,我相信你已经在互联网上的某个地方看到过。但我不认为它成熟。我会认为这样的东西更成熟:

​​>
├── model
├── website-ui
│   ├── routers
│   ├── templates
│   └── index.js    // this is router
├── website-api
│   ├── user
│   │   └── index.js    // this might be a router (API dependent
│   ├── item
│   │   └── index.js    // this might be a router
│   └── index.js    // this is router
├── index.js
└── main-router.js    // this is router

通常你甚至不会像 main-router 那样做,因为这个责任通常由 Nodejs 之外的负载均衡器承担。但每个人都必须从某个地方开始。这个实现很容易在以后升级。

不要将多个 API 与 API 版本混淆。在最好的情况下,您永远不需要 API 版本。你会这样继续:

├── website-api
│   ├── user-old
│   │   └── index.js
│   ├── user
│   │   └── index.js
│   ├── item
│   │   └── index.js    
│   ├── index-v1.js
│   └── index-v2.js

或者那个:

├── website-api-v1
│   ├── user
│   │   └── index.js
│   ├── item
│   │   └── index.js
│   └── index.js
├── website-api-v2
│   ├── user
│   │   └── index.js
│   ├── item
│   │   └── index.js
│   └── index.js

你现在不能说。你不应该在乎。当您对 API 进行更改时,您将它们向后兼容。如果你不能再这样做了,这意味着你过去犯了一些严重的错误,或者发生了大的业务变化。这是不可预测的。

拥有单独的 api 文件的好处之一是可重用性。

是的,但你现在不能说。

关于您的其他问题。 坚持 SOLID 原则。代码的每一部分都应该有一个特定的目的。
当我看到您的 router 文件夹时,我不知道那里有什么。好吧,我知道路由器,但路由器是什么?可以有一切,但什么都没有。因此不易扩展 = 不好。
当我查看我的结构时,我可以更轻松地预测其中的内容。

您应该根据目的而不是具体实现来设计架构。假设您有两个 API,因为您有两个目的。它们都是 REST 还是 GraphQL?我可以共享代码并删除重复项吗?没那么重要。如果操作不当,共享代码实际上是非常危险的。共享代码是重构最糟糕的部分,而且它通常不会提供那么多优势。

...我开始怀疑是不是我把它写得太复杂了...

取决于,这是一个 14 天的项目吗?是的,你做到了。是一年或更长时间吗?你应该更深入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 2014-11-02
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多