专栏首页忽如寄的前端周刊resource-router-middleware项目源码阅读

resource-router-middleware项目源码阅读

resource-router-middleware是一个提供restful API的Express中间件,由preact作者developit开发。 一个简单使用案例就是:

const resource = require('resource-router-middleware');
let users = [];
const huruji = {
    id:12,
    name: 'huruji',
    age: 12,
    sex: 'man'
};
const grey = {
    id: 13,
    name: 'grey',
    age: 12,
    sex: 'man'
};

users = [huruji, grey];

module.exports = resource({
   mergeParams: true,
   id: 'user',
   load: function(res,id, callback) {
       callback(null, huruji);
   },
   list: function(req, res) {
       res.json(users);
   },
   create: function(req, res) {
       var user = req.body;
       users.push(user);
       res.json(user);
   },
    read: function(req, res) {
       res.json(req.user);
    },
    update: function(req, res) {
       var id = req.params[this.id];
       for(var i = users.length;i--;) {
           if(users[i].id === id){
               users[i] = req.body;
               users[i].id = id;
               return res.status(204).send('Accepted');
           }
       }
       res.status(404).send('Not found');
    },
    delete: function(req, res) {
       var id = req.params[this.id];
       for(var i =users.length;i--;) {
           if(users[i].id===id) {
               users.splice(i,1);
               return res.status(200);
           }
       }
       res.status(404).send('Not found');
    }
});
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const userResource = require('./user');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/user',userResource);


app.listen(5000, function(err) {
    if(err) {
        return console.log(err);
    }
    console.log('server is listening port 5000')
});

可以学习的点主要是: 1、Express.Router可以提供一个对象参数

{
 mergeParams: 是否保留父级路由的req.params,且父子的req.params冲突时,优先使用子级的
caseSensitive:路由的路径是否大小写敏感,默认为false
 strict:是否启用严格模式,即/foo与/foo/区别对待
}

2、router.param的使用 3、取反运算,这个使用真的是相当巧妙 4、restful API的设计

var Router = require('express').Router;

var keyed = ['get', 'read', 'put', 'update', 'patch', 'modify', 'del', 'delete'],
    map = { index:'get', list:'get', read:'get', create:'post', update:'put', modify:'patch' };

module.exports = function ResourceRouter(route) {
    route.mergeParams = route.mergeParams ? true : false;
    // Express.Router可以提供一个对象参数
    /**
     * @param {
     * mergeParams: 是否保留父级路由的req.params,且父子的req.params冲突时,优先使用子级的
     * caseSensitive:路由的路径是否大小写敏感,默认为false
     * strict:是否启用严格模式,即/foo与/foo/区别对待
     * }
     */
    var router = Router({mergeParams: route.mergeParams}),
        key, fn, url;

    // 如果有中间件则装载中间价
    if (route.middleware) router.use(route.middleware);

    // router.param方法的回调函数的参数分别是req,res,next,params的值,params的key
    // 使用这个我们可以为路由的params找到数据之后直接定义在req对象中,供后续处理
    if (route.load) {
        router.param(route.id, function(req, res, next, id) {
            route.load(req, id, function(err, data) {
                if (err) return res.status(404).send(err);
                req[route.id] = data;
                next();
            });
        });
    }

    for (key in route) {
        // fn为对应的http method
        fn = map[key] || key;
        if (typeof router[fn]==='function') {
            // ~取反位运算,这个很有意思,三目运算符只有在~keyed.indexOf(key)为0时运算'/',取反值与原值相加为-1的原则知原值keyed.indexOf(key)为-1,也就是说
            // url = ~keyed.indexOf(key) ? ('/:'+route.id) : '/'与url = (keyed.indexOf(key) > -1) ? ('/:'+route.id) : '/';效果相同
            // 意义在于如果用户是使用keyed数组里的元素来定义键的,则使用('/:'+route.id)路由路径,否则使用'/'路由路径
            url = ~keyed.indexOf(key) ? ('/:'+route.id) : '/';
            console.log(key);
            console.log('url:' + url)
            router[fn](url, route[key]);
        }
    }

    return router;
};

module.exports.keyed = keyed;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android布局练习—计算器

    用户1515472
  • 动手实现一个AMD模块加载器(三)

    在上一篇文章中,我们的AMD模块加载器基本已经能够使用了,但是还不够,因为我们没有允许匿名模块,以及没有依赖等情况。实际上在amd的规范中规定的就是define...

    用户1515472
  • 动手实现一个最简单的redux

    redux的主要API集中在createStore函数返回值中,以下这个迷你的redux只简单实现createStore、dispatch、subscribe、...

    用户1515472
  • 你好MyBatis 中级篇

    本章节我将继续讲述MyBatis,会对上一章节的一些代码进行简化和重构,使整个程序看起来更加优雅,易扩展。

    止术
  • MyBatis-2. Mapper XML文件

    这个语句被称作 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行...

    悠扬前奏
  • MYSQL回顾(表关系相关)

    比如有两个表,分别是书籍表和出版社表。书籍和出版社是典型的多对一关系,即一本书只能由一个出版社出版,一个出版社可以出版多本书。则书籍表应该有一个外键press_...

    VV木公子
  • Python for Everything

    freesan44
  • MySQL之表的约束

    一 介绍 约束条件与数据类型的宽度一样,都是可选参数 作用:用于保证数据的完整性和一致性 主要分为: PRIMARY KEY (PK) 标识该字段为该表的...

    人生不如戏
  • MySQL数据库3分组与单表、多表查询

    select * from 表名 where 列名 in (值1,值2,。。。);

    GH
  • 如何同时压测创建和删除接口

    在最近的工作中,遇到了一批需要压测的接口,其中两个接口比较特殊:一个是创建资源接口,另外一个是删除该资源的接口。

    FunTester

扫码关注云+社区

领取腾讯云代金券