欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Express中间件简单的实现原理

程序员文章站 2022-05-14 11:54:31
上一篇理解Express的使用之后, 再总结一篇Express中间件的简单实现原理。 我们知道Express中间件就是一个个的函数, 那么怎么让这些函数有序的执行呢? 那就需要我们调用 函数。其实 函数调用的就是下一个中间件函数。 以下代码实现了简单的 注册中间件, 以及 、`post`方式的中间件 ......

上一篇理解express的使用之后, 再总结一篇express中间件的简单实现原理。

我们知道express中间件就是一个个的函数, 那么怎么让这些函数有序的执行呢? 那就需要我们调用 next 函数。其实 next函数调用的就是下一个中间件函数。

以下代码实现了简单的 app.use 注册中间件, 以及 getpost方式的中间件。其他请求方式的中间件实现同理

核心代码:

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()
}