将参数从中间件传递到表达路由器

Ele*_*to0 2 javascript node.js express

这个问题很长一段时间困扰着我,我从来没有找到一个能够清楚地向我解释的答案.

我正在使用Express 4.0,我已经制作了这个片段,向您展示我所做的解决方案,以获得我所需要的结果.

我想将参数req.method和一个路由数组controllers.routes直接传递到快速路由器,以定义方法并过滤中间件中的路由.

var controller = require( './controllers' );

module.exports = function ( app ){

    app.router.use(function ( req, res, next ){

        // function with the args before router get called
        anotherFn( app, req.method, controller );

        // Call the express router after called function with args
        next( 'route' );

    });

};

function anotherFn( app, method, controller ){

    // Express router called with args here...
    app.router[ method ]( controllers.routes,
        function ( req, res, next ){

            try{
                controller[ req.config.action ]( req, res, next );
            }catch( e ){
                next( 'error' );
            }

        }
    );

};
Run Code Online (Sandbox Code Playgroud)

它现在正在工作,但在我看来有点hacky或粗略的原因我认为函数永远不会得到解决或中间件调用anotherFn函数后调用该路径,它的奇怪是如何工作,似乎不是一个好的实践.

我担心将来这可能会给我带来异步问题,或者很难维护原因似乎不是固定代码(或者至少对我而言).

现在我的问题是,如果这是一个很好的做法,我可以保持这个原样,或者是否有另一种方法将这些参数传递给路由器似乎不那么hacky和奇怪.

cus*_*pvz 6

TL;博士

您必须记住,在基于MVC的节点服务器上必须有两个阶段:配置阶段工作阶段 ; 这是7个抽象处理层的构建基础:网络服务器(http/https/spddy/...),请求/响应中间件系统(快速/连接),路由器路由(快速路由器,简单路由器,emvici路由器) ,控制器,型号(mongo-cli/sequelize/...),最后查看(jade/ect/mustache/...)

在进入工作阶段之前,应初始化和配置所有抽象层.如果您的服务器已经收到请求,并且可能还没有查看,则它们将产生错误.您正在路由器工作状态内配置路由器/路由.


似乎那里有一些错过理解概念.中间件用于按每个请求执行.控制器(假设这里是MVC)旨在为每种数据保存操作.通常使用MVC模式,你总是有一个路由器/路由,一些框架在底层执行,其他框架允许您访问.

发现Express和大多数最知名的nodejs模块非常适合不完全遵循框架的概念,它们提供了围绕其目标的功能,但它们仅提供基本的API内容,以便您与其他人粘合.这就是为什么你在谷歌找到相同的建议,但有完全不同的实现的原因.

现在,回到正确的位置,控制器和路由器之间的绑定应该通过创建路由来完成.你正在做的事情,你每次有人提出请求时都会将路由添加到express中,这就是内存密集型/坏的方法.

我建议你在开始编码之前在抽象层中思考.让我们假设您需要控制器,模型,视图,一个路由器,一个Http服务器(不是应用程序)和一个应用程序(通常应用程序是一个中间件连接部分,可能是connect,express等等......)

  • server.js - 在这里你可以抽象一下你的服务,那就是选择它的地方,如果它是一个http/https/spdy等等......
  • app.js - 应用程序应该从服务器获取所有请求,通过您需要的一组中间件传递它们,最后但并非最不重要的是,路由器作为中间件
  • router.js - 当请求到达路由器时,它们应该已经包含了您需要的所有数据,现在是时候将它们重定向到路由了.要做到这一点,路由器应该配置他们的路由并准备就绪.在这里你应该要求routes
  • 路线/
    • index.js - 在这里您可以导出此文件夹中的所有路由,或者如果您愿意,可以在此处配置它们.每条路线都需要所需的控制器.
  • 控制器/ - 您可能不需要索引,因为每条路由都需要每个控制器.在每个控制器上,您可能需要所需的模型和视图.
  • models / - 您可能不需要索引,因为需要模型的每个控制器都需要它们.
  • views / - 视图是控制器所要求的,但在特殊情况下,它们有一个View Engine可以做到这一点.查看他们的文档以获取更多详细信息

现在,对你的案件更具代表性:

server.js

var http = require( 'http' )
var server = http.createServer()
module.exports = server
Run Code Online (Sandbox Code Playgroud)

app.js

var server = require( './server' )
var app = require( 'express' )()
module.exports = app

// Grab middlewares here...
// ...

// Now configuring router
app.use( require( './router' ) )

app.listen( server );
Run Code Online (Sandbox Code Playgroud)

router.js

var router = new require( 'express' ).Router()
module.exports = router

// Load routes
require('./routes' ).forEach(function ( route ) {
  route( router )
})
Run Code Online (Sandbox Code Playgroud)

routes/index.js

exports.user_example = require( './user_example' )
Run Code Online (Sandbox Code Playgroud)

user_example.js

var UserController = require( '../controller/user' )

module.exports = function ( router ) {
  router
    .route( '/user' )
    .post(UserController.create)
    .put(UserController.create)
  ;
  router
    .route( '/user/:id' )
    .get(UserController.view)
    .post(UserController.update)
    .put(UserController.update)
  ;
  router
    .route( '/user/delete/:id' )
    .get(UserController.delete)
  ;

}
Run Code Online (Sandbox Code Playgroud)

controller/user.js

// Here you should bind your modules

exports.create = function ( req, res, next ) {
  res.send( 200, 'created' )
}

exports.view = function ( req, res, next ) {
  res.send( 200, req.param( 'id' ) )
}

exports.update = function ( req, res, next ) {
  res.send( 200, req.param( 'id' ) )
}

exports.delete = function ( req, res, next ) {
  res.send( 200, req.param( 'id' ) )
}
Run Code Online (Sandbox Code Playgroud)

希望它有所帮助!何塞莫雷拉