美文网首页
express中间件原理及实现

express中间件原理及实现

作者: jackie季 | 来源:发表于2020-03-08 21:50 被阅读0次

    中间件是一种拦截器的思想,用于在某个特定的输入输出之间添加一些额外的处理,它最大的特点就是,一个中间件处理完,再传递给下一个中间件,App实例在运行过程中,会调用一系列的中间件。
    每个中间件可以从App实例中接收三个参数,依次是request对象(请求)、response对象(响应)、next函数(执行下一个中间件),每一个匹配的中间件都可以对request对象进行加工,并且决定是否调用next方法来执行下一个中间件。
    中间件是在管道中执行的,你可以想象一个真实的水管道,水从一端注入,到达另一端之前会经过各种仪器、阀门,这里的顺序也是很重要的一点。在express中,调用app.use可以插入一个新的管道。

    分析一下中间件的原理:
    1.app.use用来注册中间件,先收集起来;
    2.遇到HTTP请求,根据path和method进行匹配,判断触发哪些中间件;
    3.next机制,即上一个通过next触发下一个;

    那么,我们就来简单用代码实现一下:

    const http = require('http')
    const slice = Array.prototype.slice
    
    class EasyExpress {
        constructor() {
            this.routes = {
                all: [],
                get: [],
                post: []
            }
        }
    
        // 注册中间件
        register(path) {
            let 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 info = this.register.apply(this, arguments)
            this.routes.all.push(info)
        }
    
        get() {
            const info = this.register.apply(this, arguments)
            this.routes.get.push(info)
        }
    
        post() {
            const info = this.register.apply(this, arguments)
            this.routes.post.push(info)
        }
    
        listen(...args) {
            const server = http.createServer(this.callback())
            server.listen(...args)
        }
    
        callback() {
            return (req, res) => {
                let { url, method } = req
                method = method.toLowerCase()
    
                let stack = []
                const routeList = []
    
                routeList = routeList
                    .concat(this.routes.all)
                    .concat(this.routes[method])
    
                // 寻找匹配的中间件
                routeList.forEach(routeInfo => {
                    if (url.indexOf(routeInfo.path) === 0) {
                        stack = stack.concat(routeInfo.stack)
                    }
                })
    
                this.handler(req, res, stack)
            }
        }
    
        // 处理stack
        handler(req, res, stack) {
            const next = () => {
                const fn = stack.shift()
                if (fn) {
                    fn(req, res, next)
                }
            }
            next()
        }
    }
    

    next 方法不断的取出stack中的“中间件”函数进行调用,同时把next 本身传递给“中间件”作为第三个参数,每个中间件约定的固定形式为 (req, res, next) => {}, 这样每个“中间件“函数中只要调用 next 方法即可传递调用下一个中间件。

    相关文章

      网友评论

          本文标题:express中间件原理及实现

          本文链接:https://www.haomeiwen.com/subject/awgjdhtx.html