内容简介:了解 express 原理之前,你需要先掌握 express 的基本用法。关于 express 的介绍请看先回顾一下 express 使用的的过程,首先是把模块倒入,然后当做方法执行,在返回值中调用
了解 express 原理之前,你需要先掌握 express 的基本用法。
关于 express 的介绍请看 express 官网 。
基本结构
先回顾一下 express 使用的的过程,首先是把模块倒入,然后当做方法执行,在返回值中调用 use
处理路由,调用 listen
监听端口。
const express = require('express') const app = express() app.use('/home', (req, res) => { res.end('home') }) app.listen(8080, () => { console.log('port created successfully') })
根据上面的使用,我们开始构建代码。我们需要写一个 express
方法,返回一个 app
对象,有 use
和 listen
方法。
const http = require('http') const url = require('url') function express() { const app = {} const routes = []; app.use = function (path, action) { routes.push([path, action]) } function handle(req, res) { let pathname = url.parse(req.url).pathname; for (let i = 0; i < routes.length; i++) { var route = routes[i]; if (pathname === route[0]) { let action = route[1]; action(req, res); return; } } handle404(req, res); } function handle404(req, res) { res.end('404') } app.listen = function (...args) { const server = http.createServer((req, res) => { handle(req, res) }) server.listen(...args) } return app } module.exports = express
上面代码中的 use
方法的作用是把请求路径跟对应的处理函数存放在一个数组中,当请求到来的时候遍历数组,根据路径找到对应的方法执行。
动态路由
动态路由是根据参数可以动态匹配路径。
const express = require('./express') const app = express() // /home/1 // /home/2 app.use('/home/:id', (req, res) => { res.end('home') }) app.listen(8080, () => { console.log('port created successfully') })
根据路由里面的参数要匹配符合规则的路由我们需要使用正则来处理,下面代码是根据路径来生成正则的一个方法。
const pathRegexp = (path, paramNames=[], {end=false} ={}) => { path = path .concat(end ? '' : '/?') .replace(/\/\(/g, '(?:/') .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function (_, slash, format, key, capture, optional, star) { slash = slash || ''; paramNames.push(key); return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + (optional || '') + (star ? '(/*)?' : ''); }) .replace(/([\/.])/g, '\\$1') .replace(/\*/g, '(.*)'); return new RegExp('^' + path + '$') } module.exports = pathRegexp
根据路径生成正则也是有第三方模块 path-to-regexp 模块,核心原理大家值得参考。包括 Vue 和 React 的路由都使用到了这个模块。
下面我们需要开始动态映射路由。
const http = require('http') const url = require('url') const pathRegexp = require('./pathRegexp') function express() { const app = {} const routes = { 'all': [] }; app.use = function (path, action) { const keys = [] const regexp = pathRegexp(path, keys,{end:true}) routes.all.push([ { regexp, keys }, action ]); }; ['get', 'put', 'delete', 'post'].forEach(function (method) { routes[method] = []; app[method] = function (path, action) { const keys = [] const regexp = pathRegexp(path, keys, {end:true}) routes[method].push([ { regexp, keys }, action ]); }; }); const match = function (pathname, routes, req, res) { for (var i = 0; i < routes.length; i++) { let route = routes[i]; let reg = route[0].regexp; let keys = route[0].keys; let matched = reg.exec(pathname); if (matched) { let params = {}; for (let i = 0, l = keys.length; i < l; i++) { let value = matched[i + 1]; if (value) { params[keys[i]] = value; } } req.params = params; let action = route[1]; action(req, res); return true; } } return false; }; function handle(req, res) { let {pathname, query} = url.parse(req.url, true); req.query = query let method = req.method.toLowerCase(); if (routes.hasOwnProperty(method)) { if (match(pathname, routes[method], req, res)) { return; } else { if (match(pathname, routes.all, req, res)) { return; } } } else { if (match(pathname, routes.all, req, res)) { return; } } handle404(req, res); } function handle404 (req, res) { res.end('404') } app.listen = function (...args) { const server = http.createServer((req, res) => { handle(req, res) }) server.listen(...args) } return app } module.exports = express
其中 express
会把请求的方法都代理到 app
中作为属性的方式来方便用户使用。
const express = require('./express') const app = express() app.use('/home/:id', (req, res) => { console.log(req.params) res.end('home') }) // app.get // app.post app.get('/user', (req, res) => { console.log(req.query) res.end('user') }) app.listen(8080, () => { console.log('port created successfully') })
express 会在请求对象中加一些属性,会把路径参数作为请求时的 params
属性,会把查询字符串作为请求时的 query
属性。大多数中间件也是这个原理,如 body-parser 模块,给它加个 body
属性即可。
通过GitHub查看代码请点击:
以上所述就是小编给大家介绍的《express基本原理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- java反射原理, 注解原理
- Webpack 原理(二):加载原理
- Docker原理之 - CGroup实现原理
- 【Vue原理】响应式原理 - 白话版
- Docker实现原理之 - OverlayFS实现原理
- UAV MOF工作原理之Agent注入机制原理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms in Java, Part 5
Robert Sedgewick / Addison-Wesley Professional / 2003-7-25 / USD 54.99
Algorithms in Java, Third Edition, Part 5: Graph Algorithms is the second book in Sedgewick's thoroughly revised and rewritten series. The first book, Parts 1-4, addresses fundamental algorithms, data......一起来看看 《Algorithms in Java, Part 5》 这本书的介绍吧!