上一篇理解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()
}

Express中间件简单的实现原理的更多相关文章

  1. Express中间件的原理及实现

    在Node开发中免不了要使用框架,比如express.koa.koa2拿使用的最多的express来举例子开发中肯定会用到很多类似于下面的这种代码 var express = require('exp ...

  2. Express中间件原理详解

    前言 Express和Koa是目前最主流的基于node的web开发框架,他们的开发者是同一班人马.貌似现在Koa更加流行,但是仍然有大量的项目在使用Express,所以我想通过这篇文章说说Expres ...

  3. express中间件原理 && 实现

    一.什么是express中间件? 什么是express中间件呢? 我们肯定都听说过这个词,并且,如果你用过express,那么你就一定用过express中间件,如下: var express = re ...

  4. express 中间件的简单应用与实现

    express 中间件的简单应用与实现 看了慕课网双越老师的课之后结合自己的理解做了一些简单的总结,如有不恰当之处,欢迎指正. 提到 express 就不得不提到中间件,接下来就简单的介绍一下 exp ...

  5. 1.express中间件的简介

    express中间件的意思 1, 中间件是一个模块.在js中,模块意味着函数,所以中间件是一个函数.那么这个函数长什么样子? 这还要从中间件的功能说起,它拦截http 服务器提供的请求和响应对象,执行 ...

  6. vue+webpack+express中间件接口使用

    环境:vue 2.9.3; webpack 目的:接口的调用 跨域方式: 1.express中间的使用 2.nginx代理 3.谷歌浏览器跨域设置 -------------------------- ...

  7. redux中间件和redux-thunk实现原理

    redux-thunk这个中间件可以使我们把这样的异步请求或者说复杂的逻辑可以放到action里面去处理,redux-thunk使redux的一个中间件,为什么叫做中间件 我们说中间件,那么肯定是谁和 ...

  8. 【nodejs原理&源码赏析(2)】KOA中间件的基本运作原理

    [摘要] KOA中间件的基本运作原理 示例代码托管在:http://www.github.com/dashnowords/blogs 在中间件系统的实现上,KOA中间件通过async/await来在不 ...

  9. Node.js连接Mysql,并把连接集成进Express中间件中

    引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...

随机推荐

  1. jquery——元素节点操作

    插入节点: 1.append()和appendTo():在现存元素的内部,从后面插入元素 <script type="text/javascript"> $(funct ...

  2. 004 Median of Two Sorted Arrays 两个有序数组的中位数

    There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the median of the two ...

  3. Windows沾滞键设置

    控制面板----轻松使用-----轻松使用设置中心------更改键盘的工作方式

  4. how to keep impact-crusher in good condition

    how to keep impact-crusher in good condition Why we have to maintenance impact crusher? As we talked ...

  5. Java日志格式应该是占位符还是字符串拼接

    背景 ​ 上次在群中,有个群友说自己把所有项目中,所有使用占位符打印日志的方式都修改成为了字符串拼接的方式,因为他曾经看了一篇文章,说字符串拼接的形式比占位符形式的性能更好,这个话题引起了大家的广泛讨 ...

  6. Toad for Oracle针对于Oracle数据库的可视化管理工具使用

    Toad for Oracle安装包下载地址:http://pan.baidu.com/s/1mgBOLZU 在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工 ...

  7. H5移动端原生长按事件

    // 函数名longpress// 参数为: 需长按元素的id.长按之后处理函数func function longPress(id, func,timeout=500) { var timeOutE ...

  8. Error: connect ECONNREFUSED 127.0.0.1:8080

    Error: connect ECONNREFUSED 127.0.0.1:8080    at Object.exports._errnoException (util.js:1018:11)    ...

  9. Linux下安装软件遇见的问题汇总

    1.安装monodevelop 安装环境Linux Mint17.1 在软件在中心直接安装monodevelop,安装完成后直接启动界面“一闪而过”,解决办法: 软件中心安装 mono-complet ...

  10. ubuntu命令收集

    软件操作: - sudo apt-get install xxx 安装软件 - sudo apt-get --purge remove XXX 卸载软件 - sudo apt-get -f insta ...