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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论