Paypal开源nodejs框架研究(二)KrakenJs之Enrouten

原创 2013年12月02日 11:33:12

Enrouten:用于 Express 的路由(route)配置中间件(初始化与配置模块)https://github.com/paypal/express-enrouten


  我觉得这称不上一个中间件,为什么!express或者说connect的中间件,至少要有截获和转发request的功能吧,所以这个最多成的上是对express原有route功能的增强。其实看了他的代码,我觉得非常熟悉,因为我的route代码也是这么设计的,哈哈。

  我使用Nodejs的时候,有一点不爽就是,对于route的注册和实现是分离的,route的注册是在app.js里面,而route的实现是放在route.js里面的,很多时候,如果要添加一个route,就不得不同时修改2个文件,这不仅给开发,还给维护带来很大的不变,我觉得Enrouten这个小框架可能就是为了解决这个问题。先看看他的代码实例:

一、注册route,Enrouten支持2种注册route的方法,一个是指定一个目录,一个是指定一个route的定义集合。

// 第一种方法
enrouten(app).withRoutes({
    directory: 'controllers'
});


// 第二种方法
enrouten(app).withRoutes({
    routes: [
        { path: '/',    method: 'GET', handler: require('./controllers/index') },
        { path: '/foo', method: 'GET', handler: require('./controllers/foo') }
    ]
});

  对于第一种方法,Enrouten会遍历改目录下所有的js文件,假如那个js文件export出来的是一个函数且仅仅是一个函数,那么就调用那个函数,并且传入express的实例,那个,这个函数该怎么写呢:

module.exports = function (app) {
    app.get('/', function (req, res) {
        // ...
    });
};

明白了吧,这个函数就把原来在app.js代码,移到了route内部(在Enrouten里面应该叫做controller吧)


对于第二种方法,我再贴一遍代码:

// 第二种方法
enrouten(app).withRoutes({
    routes: [
        { path: '/',    method: 'GET', handler: require('./controllers/index') },
        { path: '/foo', method: 'GET', handler: require('./controllers/foo') }
    ]
});

  这个代码很有误导性,看上去,好像已/foo开头的route都定义在了./controllers/foo那个文件里面,通过这个定义,就可以把所有对foo的request都handle了。但可是,可但是实际上是什么呢?Enrouten只不过,遍历这个数组,对里面每个route定义,调用app[method](def.path, def.handler),说的再明白点,就是app.get("/foo", handler)。所以没什么大花头哦。


  好,再来看看我自己的设计,我有个名为AbstractRoute的基类,里面有一个公共的函数addRequestHandlers,这个函数需要你传入express实例,然后会调用受保护的_addRequestHandlers工具函数,这个工具函数和Enrouten做的差不多,挨个遍历定义,然后帮你注册routes。

"use restrict";
_ = require('underscore')
should = require('should')

module.exports = class AbstractRoute
#public:
    addRequestHandlers: (server)->
        @_addRequestHandlers(server, [])

#protected:
    _addRequestHandlers: (app, routeRequests)->
        should.exist(app, routeRequests)
        for routeRequest in routeRequests
            method = app[routeRequest.method] || app.get
            method.call(app, routeRequest.url, _.bind(routeRequest.handler, @))


这个是每个route的代码,从AbstractRoute继承,重写addRequestHandlers函数,把route定义传给_addRequestHandlers()函数。

module.exports = class CerRoute extends AbstractRoute
#public: 
    addRequestHandlers: (@m_app) ->
        should.exist(@m_app)
        routeRequests = [
            new RouteRequest("get", "/", @handleIndexPage)
            new RouteRequest("get", "/cer/:idType(group|product)/:id", @handleProductIndexPage)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/index", @handleAjaxProductIndex)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/topCrashCommands", @handleAjaxTopCrashCommands)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/weeklyCrashCount", @handleAjaxWeeklyCrashCount)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/weeklyCrashCountPerUser", @handleAjaxWeeklyCrashCountPerUser)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/fixRate", @handleAjaxFixRate)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/osBreakDown", @handleAjaxOsBreakDown)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/bucket", @handleAjaxBucket)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/realTimebucket", @handleAjaxRealTimebucket)
            #new RouteRequest("get", "/cer/:idType(group|product)/:id/dataMining", @handleAjaxDataMining)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/sendReport", @handleAjaxSendReport)
            new RouteRequest("post", "/cer/:idType(group|product)/:id/postReport", @handleAjaxPostReport)

            new RouteRequest("get", "/cer/:idType(group|product)/:id/data/researchRate", @handleDataGetResearchRate)
            new RouteRequest("get", "/cer/:idType(group|product)/:id/data/fixRate", @handleDataGetFixRate)

        ]
        @_addRequestHandlers(@m_app, routeRequests)


RouteRequest又是一个类,很简单很简单:

should = require('should')

module.exports = class RouteRequest
    constructor: (@method, @url, @handler)->
        should.exist(@method, "parameter 'method' can not be null")
        should.exist(@url, "parameter 'url' can not be null")
        should.exist(@handler, "parameter 'handler' can not be null")

在app.js里面的调用也很简单:

cerRoute = new (require('./lib/route/CerRoute'))();
cerRoute.addRequestHandlers(server);

我这样设计有2个优点:

1. 面对对象

2. 把route的注册和实现放在一个类/文件里面,好管理,好维护。

缺点:

1. 没有考虑到,把这个AbstractRoute作为一个单独的module独立出来,变成一个框架 :)




NodeJS无所不能:细数10个令人惊讶的NodeJS开源项目

在几年的时间里,NodeJS逐渐发展成一个成熟的开发平台,吸引了许多开发者。有许多大型高流量网站都采用NodeJS进行开发,像PayPal,此外,开发人员还可以使用它来开发一些快速移动Web框架。 ...
  • Kaitiren
  • Kaitiren
  • 2013年12月19日 09:52
  • 23571

转 - 最流行的Node.js快速开发框架大荟萃

原文 见  http://www.gbtags.com/gb/share/3032.htm
  • supermig
  • supermig
  • 2014年04月09日 15:57
  • 2215

10 个最适合 Web 和 APP 开发的 NodeJS 框架

在浏览器以外运行 JavaScript 对于 JavaScript 爱好者来说非常神奇,同时也肯定是 web 应用程序开发界最受欢迎的进步之一。全球各地的开发者张开双臂拥抱 NodeJS。 对于...
  • Richard_Jason
  • Richard_Jason
  • 2016年10月24日 14:42
  • 1208

十大 Node.js 的 Web 框架

1、Node.js 开发框架 Sail.js Sails.js 就像是 Node.js 平台上的 Rails 框架。这是一个可靠可伸缩的开发框架,面向服务的架构,提供数据驱动的 API 集合。用来开...
  • u012017783
  • u012017783
  • 2017年06月19日 08:47
  • 3359

10个最好的 Node.js MVC 框架

Node.js 是最流行的 JavaScript 服务端平台,它允许建立可扩展的 Web 应用程序。Node.js 包含不同类型的框架,如 MVC 框架、全栈框架、REST API  以及大量的服...
  • ejinxian
  • ejinxian
  • 2016年09月12日 12:33
  • 812

从Java的角度理解前端框架,nodejs,reactjs,angularjs,requirejs,seajs

【突然领悟】 今天看了一遍reactjs,突然发现和自己一直用的freemarker的宏十分相似, 突然领悟了很多前端吊炸天的概念,框架,特写此文,欢迎批评指正。 【nodejs】 官网:http...
  • uikoo9
  • uikoo9
  • 2015年05月26日 00:26
  • 37597

Node.js微服务+流水线服务框架的设想

Node.js微服务+流水线服务框架的设想 要点: 每个微服务从代码实现来看,就是一个JS函数,输入是一个JSON对象,输出也是一个JSON对象 框架负责将其转换为基于URL输入和输出的W...
  • cteng
  • cteng
  • 2016年02月02日 18:00
  • 2133

当今最流行的Node.js应用开发框架简介

快速开发而又容易扩展,高性能且鲁棒性强。Node.js的出现让所有网络应用开发者的这些梦想成为现实。但是,有如其他新的开发语言技术一样,从头开始使用Node.js的最基本功能来编写代码构建应用是一个非...
  • binyao02123202
  • binyao02123202
  • 2015年02月24日 12:22
  • 4489

如何利用Node.js 构建分布式集群

在软件定义的世界里,企业通过Web应用和移动应用程序来提供大部分的服务,而Node.js迅速成为时下最为流行的一个平台之一,就和它可以搭建 响应速度快、易于扩展的web应用和移动应用很很大关系,并凭借...
  • mergerly
  • mergerly
  • 2016年04月20日 18:05
  • 1675

深入浅出node.js游戏服务器开发1——基础架构与框架介绍

深入浅出node.js游戏服务器开发1——基础架构与框架介绍 游戏服务器概述 没开发过游戏的人会觉得游戏服务器是很神秘的东西。但事实上它并不比web服务器复杂,无非是给客户端提...
  • xinshou_jiaoming
  • xinshou_jiaoming
  • 2013年04月19日 14:09
  • 3783
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Paypal开源nodejs框架研究(二)KrakenJs之Enrouten
举报原因:
原因补充:

(最多只允许输入30个字)