Nodejs中Router和Controller的紧耦合及一般做法探讨
Nodejs中Router和Controller的紧耦合及一般做法探讨
N-Blog的教程,和网上大多数主流教程,Router和Controller紧密耦合。虽然Router也是Controller的一部分,但是这样看怎么样也不是很优雅。
所以一般而言,都会怎么做?没有一个清晰的路由表很不爽的。
我目前的做法是将代码导出模块,然后在路由表传入。
这是routers/index.js
var Auth = require('../controller/authorization'),
ArticleHandler = require('../controller/articles');
module.exports = function(app) {
// router of index
app.get(’/’, function(req, res){res.end(“Hello world!”)});
// router of /article
app.get('/articles', ArticleHandler.list_articles);
app.post('/articles', Auth.auth, ArticleHandler.add_article);
// router of /article/(.*)
app.put('/articles/:id', Auth.auth, ArticleHandler.modify_article);
app.get('/articles/:id', ArticleHandler.get_a_article);
app.delete('/articles/:id', Auth.auth, ArticleHandler.remove_article);
// router of /api-auth
app.post('/api-auth', Auth.get_token);
// router of /tags
app.get('/tags', function(req, res){});
// todo
};
然后controller里有articles.js和authorization.js。
以articles.js为例,里面是一个Article类,然后暴露Article的接口。
var Article = require('../models/articles'),
User = require('../models/users'),
Auth = require('authorization');
function ArticleHandler() {
//Article Handlers
}
ArticleHandler.list_articles = function(req, res) {
// some statements
};
// Others
module.exports = ArticleHandler;
感觉比较蛋疼的。
不知你们的通用做法是?
Node.js 中 Router 和 Controller 的紧耦合及一般做法探讨
在 Node.js 开发中,Router 和 Controller 的紧密耦合是一个常见的问题。尽管 Router 本身可以被视为 Controller 的一部分,但这种紧耦合的方式使得代码难以维护和扩展。本文将探讨如何通过解耦 Router 和 Controller 来提高代码的可维护性和可读性。
当前的实现方式
当前的实现方式是将 Router 和 Controller 紧密耦合在一起,如以下示例:
// routers/index.js
var Auth = require('../controller/authorization'),
ArticleHandler = require('../controller/articles');
module.exports = function(app) {
// router of index
app.get('/', function(req, res){res.end("Hello world!")});
// router of /article
app.get('/articles', ArticleHandler.list_articles);
app.post('/articles', Auth.auth, ArticleHandler.add_article);
// router of /article/(.*)
app.put('/articles/:id', Auth.auth, ArticleHandler.modify_article);
app.get('/articles/:id', ArticleHandler.get_a_article);
app.delete('/articles/:id', Auth.auth, ArticleHandler.remove_article);
// router of /api-auth
app.post('/api-auth', Auth.get_token);
// router of /tags
app.get('/tags', function(req, res){});
// todo
};
在 controllers/articles.js
中,我们定义了一个 ArticleHandler
类来处理与文章相关的请求:
// controllers/articles.js
var Article = require('../models/articles'),
User = require('../models/users'),
Auth = require('../controller/authorization');
function ArticleHandler() {
// Article Handlers
}
ArticleHandler.list_articles = function(req, res) {
// some statements
};
ArticleHandler.add_article = function(req, res) {
// some statements
};
ArticleHandler.modify_article = function(req, res) {
// some statements
};
ArticleHandler.get_a_article = function(req, res) {
// some statements
};
ArticleHandler.remove_article = function(req, res) {
// some statements
};
module.exports = ArticleHandler;
解耦 Router 和 Controller
为了更好地解耦 Router 和 Controller,我们可以使用 Express Router 来创建独立的路由处理器。这样每个路由都可以独立管理其逻辑,而不必依赖于特定的 Controller。
首先,创建一个独立的路由处理器文件 routes/articles.js
:
// routes/articles.js
const express = require('express');
const router = express.Router();
const ArticleHandler = require('../controller/articles');
router.get('/articles', ArticleHandler.list_articles);
router.post('/articles', ArticleHandler.add_article);
router.put('/articles/:id', ArticleHandler.modify_article);
router.get('/articles/:id', ArticleHandler.get_a_article);
router.delete('/articles/:id', ArticleHandler.remove_article);
module.exports = router;
然后,在主路由器文件 routers/index.js
中引入这些独立的路由处理器:
// routers/index.js
const express = require('express');
const app = express();
const articlesRouter = require('./articles');
app.use('/articles', articlesRouter);
app.get('/', function(req, res){res.end("Hello world!")});
app.post('/api-auth', require('../controller/authorization').get_token);
app.get('/tags', function(req, res){});
module.exports = app;
这种方式不仅使代码更加清晰,还便于管理和扩展。每个路由处理器都独立管理自己的逻辑,而不需要依赖于特定的 Controller。
总结
通过将 Router 和 Controller 解耦,我们可以提高代码的可维护性和可读性。使用独立的路由处理器文件可以使每个路由逻辑更加清晰,并且便于管理和扩展。希望这种做法能帮助你更好地组织你的 Node.js 应用程序。
另外callback真是忧伤,让写出来的代码很脏,也不算优雅。
不过令人欣慰的是有中间件这个东西。要不然更蛋疼了。
没人鸟我=-=
乍一看这么写并没有什么不好的啊?不知道你哪里不满意~
callback的嵌套问题,可以交个promise来解决吧~
controller这个东西除了组织代码没看出来有什么用,组织代码可以用命名空间或者子目录, web框架只需要router,handle就可以了
在Node.js项目中,Router
和Controller
的耦合问题是一个常见的设计挑战。为了提高代码的可维护性和扩展性,可以采取以下方法来解耦这两个部分。
通用做法:使用中间件和独立的控制器
- 创建一个独立的路由文件,其中只定义路由而不直接调用控制器。
- 在控制器文件中,提供与HTTP请求对应的处理逻辑。
示例代码
假设我们有一个简单的博客应用,其中包含文章相关的API。以下是重构后的代码:
1. 路由文件 routers/articleRoutes.js
const express = require('express');
const articleRouter = express.Router();
const articleController = require('../controllers/articleController');
articleRouter.route('/')
.get(articleController.listArticles)
.post(articleController.addArticle);
articleRouter.route('/:id')
.get(articleController.getArticle)
.put(articleController.updateArticle)
.delete(articleController.deleteArticle);
module.exports = articleRouter;
2. 控制器文件 controllers/articleController.js
const Article = require('../models/articleModel');
const { checkAuth } = require('../middleware/authMiddleware');
exports.listArticles = async (req, res) => {
const articles = await Article.find();
res.json(articles);
};
exports.addArticle = async (req, res) => {
const { title, content } = req.body;
const newArticle = new Article({ title, content });
await newArticle.save();
res.status(201).json(newArticle);
};
exports.getArticle = async (req, res) => {
const { id } = req.params;
const article = await Article.findById(id);
if (!article) return res.status(404).send('Article not found');
res.json(article);
};
exports.updateArticle = async (req, res) => {
const { id } = req.params;
const { title, content } = req.body;
const updatedArticle = await Article.findByIdAndUpdate(id, { title, content }, { new: true });
if (!updatedArticle) return res.status(404).send('Article not found');
res.json(updatedArticle);
};
exports.deleteArticle = async (req, res) => {
const { id } = req.params;
const deletedArticle = await Article.findByIdAndDelete(id);
if (!deletedArticle) return res.status(404).send('Article not found');
res.status(204).send();
};
3. 主应用文件 app.js
const express = require('express');
const app = express();
const articleRoutes = require('./routers/articleRoutes');
const authRoutes = require('./routers/authRoutes');
app.use(express.json());
app.use('/articles', articleRoutes);
app.use('/auth', authRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
通过这种方式,Router
文件仅负责定义路由和传递给控制器,而控制器则专注于业务逻辑。这使得代码更易于维护和扩展。