Express中间件简单的实现原理
2024-09-01 15:14:45
上一篇理解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()
}
最新文章
- sublime text 3 + python配置,完整搭建及常用插件安装
- iOS 之消息推送(个推)---个人小结
- jquery load 和 iframe 比较
- Linux C编程学习之开发工具2---GDB调试器
- oracle普通用户登录em
- Introduction of Open CASCADE Foundation Classes
- Python强化训练笔记(三)——词频的统计
- c++11中的for简化用法
- magento多语言中文语言包
- canvas 绘点图
- 敏捷开发的特点(转自MBAlib)
- Intent携带额外的数据的方法
- android sdk 深入理解adb
- Linux - 在Ubuntu下永久修改主机名
- 【转】HTML CANVAS
- js来判断设备类型
- Vue混入
- Centos7 安装配置mysql5.6
- Django 跨域请求
- c# 后台post,包含file文件
热门文章
- Proxy opening connection toSpringClound配置豪猪hystrixDashboard发生
- K 大神的博弈知识汇总
- python入门之paramiko模块
- 类成员函数的重载、覆盖和隐藏区别 (C++)(转)
- mysql服务器查询慢原因分析方法
- .net 中的托管与非托管
- Oracle同义词。。。
- hibernate课程 初探单表映射1-9 创建关系映射文件
- NOIP2013Day1T3 表示只能过一个点
- npm warn weex @1.0.0 no repository field