使用 NodeJS 作为 HTTP 服务器 - 如何避免意大利面条?

问题描述 投票:0回答:2

我想使用nodejs作为我正在开发的项目的轻量级网络服务器。我主要是一名 PHP 程序员,所以我的做法与我习惯的不同。

在此应用程序中,我使用 Angular 来请求一些数据。我想将其格式化为“/get/some_data”。在我的节点端,我使用 connect 并将其静态指向我的 http 目录。

现在,当我请求一些数据时,人们似乎唯一推荐的就是查找该请求并将其传回。这比文件结构的组织性要差得多,就像我习惯的每个文件处理请求的地方一样。

var connect = require("connect");
var app = connect();

app.use(connect.static("/my_http_dir"));
app.use(function(req, res)
{
    if(req.originalUrl == "foo")
    {
        // do something relating to foo
    }
    else if(req.originalUrl == "bar")
    {
        // do something relating to bar
    }
    else
    {
        // do nothing
    }
});

connect.createServer(app).listen(80);

那么用什么来组织这个呢?我是否需要创建一个获取处理程序、放置处理程序、删除处理程序、发布处理程序等,并将“文件”传递给 switch 语句?

node.js express routes node.js-connect
2个回答
3
投票

express.js 内置了一个非常强大的路由引擎。您应该查看 应用程序路由文档 并熟悉它。

要回答您的问题,您可以这样做:

app.get('/foo', function(req,res){
  // foo 
})

app.get('/bar', function(req,res){
  // bar 
})

或者,您可以使用参数值

app.get('/api/:action', function(req,res){
  // action can be foo, bar, whatever... 
  // access action from req.params['action']
})

或者,您可以使用正则表达式,如文档所示:

app.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function(req, res){
  var from = req.params[0];
  var to = req.params[1] || 'HEAD';
  res.send('commit range ' + from + '..' + to);
});

但是,是的,您应该单独声明每个动词。


1
投票

除了 Jim 所说的之外,我还会添加另一种模式,可以使您的代码更简洁。

在单独的函数中验证路由参数

如果您使用带有参数的路由,例如

app.get('/blog/:slug', ...
,那么您可以使用
app.param
来验证给定的
slug
是否存在并执行必要的操作(发送
404
或将您的请求传递给另一个如果您的数据库中没有该
slug
,则路由或加载由给定
slug
标识的博客文章),例如

 function slugParam (req, res, next, slug) {
    Post.findBySlug({ slug: slug }, function (err, post) {
        if (err) return res.send(500, 'SERVER ERROR');
        if (!post) return res.send(404);

        res.locals.post = post; // you will be able to access 'post' in your template
        next();
    })
}

当您设置应用程序时,您必须调用 app.param 例如

app.param('slug', slugParam);

使用这种方法,如果存在给定的 slug 标识的帖子,则无需检查请求处理程序 - 非常干净的方法。

将请求处理函数拆分为中间件函数

您还可以将请求处理函数拆分为几个更小的(更干净的)函数并按顺序调用它们(实际上express会为您调用它们)。比方说,您建立了一个讨论论坛,并且您有这样的路线:

app.get('/forum/:fid/thread/:tid', function(){
    // ...
})

您需要在单个函数中处理论坛和线程加载 - 很快您就会看到意大利面条式代码(特别是这两个操作都将异步执行)。为了修复它,您可以将该功能拆分为独立的功能,负责一个功能,例如加载论坛、加载线程等。 示例:

function loadFormum (req, res, next) { Forum.load(/* params here */, function (err, forum) { if (err) return res.send(500); if (!forum) return res.send(404); res.locals.forum = forum; next(); }) } function loadThread (req, res, next) { // you can use forum from res.locals.forum here Forum.findThread(/* params here */, function (err, thread) { if (err) return res.send(500); if (!thread) return res.send(404); res.locals.thread = thread; next(); }) } app.get('/forum/:fid/thread/:tid', loadFormum, loadThread, function(){ // cleaner code })

或者

var forumMiddleware = [loadForum, loadThread] app.get('/forum/:fid/thread/:tid', forumMiddleware, function(){ // cleaner code })

使用这种方法,函数可能会相互依赖,即 
loadForum

加载模型,然后由

loadThread
使用。您可以使用任意数量的中间件函数,以保持代码清晰。

我希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.