[nodejs]为什么自己不为express写一个autoRoutes呢(二)?

根据上次的尝试,我觉得自动化的感觉还远远不够,首先是路由方面,虽然可以根据文件创建路由逻辑,但是非常重要的一点,路由的路径还是得手动填写。不仅是路由的路径,还有请求的办法,这点给人的感觉就是非常不智能了。

所以这次这个(二),就是要在原来的代码基础上做改进,要实现路由路径依据文件路径创建,请求方法根据文件名创建。而在文件里面,你只需要写两方面的内容,一个是实现路由逻辑,另一方面则是写好文档。

在这个文档方面我有三个想法,第一种想法是,在每个路由文件目录下加一个readme.md文件,然后把这个路由接口的文档写在里面,最后初始化加载路由文件的同时也读取这些readme.md的内容存储起来,然后写一个接口专门输出这些内容,再配合前端,自动构建起一个接口文档。

第二种想法是,在第一种想法的基础上,在注册路由的同时,同时也注册一个/api/doc/接口路由的接口,专门输出该路由的readme.md内容。简单讲,就是将初始化一次性读取变为分步读取吧。。。是不是有种懒加载的味道?23333.。。。

第三种想法,继承我之前的思路,直接把文档写在一个文件里面。

在这里,因为我懒(竟然这么恬不知耻的明说了?,就直接做第三种想法吧,想想每次写路由都要创建两个文件,想想都烦,而且还要用markdown写一堆相似的结构。。。这不智能对吧?渲染的工作啊,还是交给前端来,什么markdown和html都去他丫的。

好了,废话了那么多,接下来该干♂正事了。

实现


其实自动化构建文件路径路由,其实只需要一个小小的改动而已:

    var method='get';
    var route='/api/boo';
    var success=function(req,res){}
    app[method](route,success);

这里的app是express的实例,这个也是express注册路由的方法。很简单,只要把method换成遍历得到的路由文件名,比如"GET.js"的GET,然后再把它变成小写,这样就变成了:app.get(route,success)了,其余的POST|PUT|PATCH|DELET也是同理。

然后是route,这个你遍历文件夹的时候,文件路径是可得的,只要将这个文件路径拿过来,去掉有后缀名的文件名部分,就(可以吃了)可以用来当文件路径了。

不过,之前也说过,要实现RESTful式的API嘛(不懂RESTful的可以看一下阮一峰老师的介绍),有些接口需要实现后面路径自定义,比如我要根据一个id获取一篇文章的内容,首先文章的接口假如是GET /api/articles/,它的query是?aid=123456789,那么我希望能这样获取:GET /api/articles/aid/123456789或者直接GET /api/articles/123456789,但是,你用文件夹路径已经定死了,也不可能新建一个名字为*的文件夹(至少我不推荐这样做)。所以,这个是要考虑的问题。当然我相信这个小小的问题难不了大家。

我是这样做的,规定在文件名前面加个~号,比如/api/articles/~GET.js,那么该路径就会被解释为:/api/articles/*,即只要包含前面这部分的任何请求路径都由这个文件处理。这样就解决啦。什么?你想实现诸如/api/*/aid这种路由?额。。。这个。。。。等我想到方法再实现吧。。。

最后是success,这个不用说,肯定是路由文件的处理函数啦。

代码


整体代码也很简单,不过二十几行而已。。。

    var path=require('path');
    var fs=require('fs');
    var list=[];
    function readdir(dirPath, rname) {
        var arr = fs.readdirSync(dirPath);
        arr.forEach(function(item) {
            var next = path.join(dirPath, item);
            var api = rname + '/' + item;
            var stat = fs.statSync(next);
            if (stat.isDirectory()) {
                readdir(next, api);
            } else {
                if (/^[~]*(GET|POST|PUT|PATCH|DELET).js$/.test(item)) {
                    var method = item.replace(/(~|\.js)/g, '').toLowerCase();
                    var requirePath = next.replace('.js', '');
                    var route = api.replace(/\/[~]*(GET|POST|PUT|PATCH|DELET)\.js$/, '');
                    if (/~/g.test(item)) { //判断是否路由后面路径自定义
                        route += '/*';
                    }
                    var files = require(requirePath);
                    app[method](route, files.success);
                    files.info['route'] = route;
                    files.info['method'] = method;
                    files.info['index'] = list.length;
                    list.push(files.info);
                }
            }
        })
    }

很惭愧,这里做了一点点微小的工作:

  • 首先对比先前代码,这里不再直接把所有.js文件读进来了,只是读那些GET.jsPOST.js等等文件,这是为了方便。。。模块化?姑且称之为模块化吧,假如一个路由逻辑很复杂,处理起来很烦,或者全部处理方法堆在一个文件里面很不好看的时候,难免require大法好,为了相对路径读取方便,最好就是写在同级目录下,如:
        api
          ├─articles
         ...  ├─ ~GET.js
              ├─ POST.js
              └─ get.js
    

这个get.js肯定是不会被读进去的,所以可以放心的当做分模块的处理文件。

  • 其次,就是files.info['method'] = method;这句,这意味着,你在路由文件里面不需要再写method/route这两个info了。然后加了个index,其实这个并没啥卵用,就是为了让前端渲染的时候方便看第几个而已。

  • 最后,RESTful api不是还要求要把api的版本写在接口路径上吗?比如:
    api/v1/articles/aid/123456789,这个v1代表着版本号。这里也实现了,把原先那个用来记录文件require路径参数pathStr改为了可以在接口前添加版本或者其他信息的一个重命名作用的rname参数。比如:

    rname
    第一个参数是放路由文件的文件夹,第二个参数是将所有路由前面都加上api/v1,然后请求路径就变成了:
    rname

  • 最后(刚才不是已经最后了么?),作为一个前端,接口文档,给别人看的东西一定要做得好:

    接口文档

啦啦,就这样~~鬼知道有没有(三).....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容