Express中间件简单的实现原理
程序员文章站
2022-12-27 08:34:11
上一篇理解Express的使用之后, 再总结一篇Express中间件的简单实现原理。 我们知道Express中间件就是一个个的函数, 那么怎么让这些函数有序的执行呢? 那就需要我们调用 函数。其实 函数调用的就是下一个中间件函数。 以下代码实现了简单的 注册中间件, 以及 、`post`方式的中间件 ......
上一篇理解express的使用之后, 再总结一篇express中间件的简单实现原理。
我们知道express中间件就是一个个的函数, 那么怎么让这些函数有序的执行呢? 那就需要我们调用 next
函数。其实 next
函数调用的就是下一个中间件函数。
以下代码实现了简单的 app.use
注册中间件, 以及 get
、post
方式的中间件。其他请求方式的中间件实现同理
核心代码:
const next = () => { const stack = stacks.shift() if(stack) { stack(req, res, next) } } next()
stacks就是一个数组队列, 存放所有符合规则的中间件函数。遵循先进先出
的原则。也就是最先注册的中间件函数最先执行。
实现代码
const http = require('http') const slice = array.prototype.slice class express { constructor() { this.router = { all: [], // 匹配所有额中间件函数 get: [], post: [] } } /** * 这里整合中间件 * @param {string} path * @returns {object} */ middlewarehandler(path) { const info = {} if (typeof path === 'string') { info.path = path info.stack = slice.call(arguments, 1) // 中间件数组 } else { info.path = '/' info.stack = slice.call(arguments, 0) } return info } use() { const allstack = this.middlewarehandler(...arguments) this.router.all.push(allstack) } get() { const getstack = this.middlewarehandler(...arguments) this.router.get.push(getstack) } post() { const poststack = this.middlewarehandler(...arguments) this.router.post.push(poststack) } /** * * @param {string} method * @param {string} url * @returns {array} */ accordstack(method, url) { let stacks = [] stacks = stacks.concat(this.router.all) stacks = stacks.concat(this.router[method]) return stacks .filter(stack => { return url.indexof(stack.path) !== -1 }).map(item => item.stack[0]) } handler(req, res, stacks) { // 函数表达式 const next = () => { const stack = stacks.shift() if(stack) { stack(req, res, next) } } next() } callback() { return (req, res) => { res.json = data => { res.setheader('content-type', 'application/json') res.end(json.stringify(data)) } // 拿到请求的方法和url, 对中间件函数进行筛选 const {method, url} = req const stacks = this.accordstack(method.tolowercase(), url) this.handler(req, res, stacks) } } listen(...args) { const server = http.createserver(this.callback()) server.listen(...args) } } // 工厂模式, 导出一个实例对象 module.exports = () => { return new express() }
上一篇: PHP之短标签开启设置
下一篇: 彻底弄懂ES6中的Map和Set