美文网首页JavaScript 进阶营
js中不同框架中间件实现的区别

js中不同框架中间件实现的区别

作者: 勤奋的大鱼 | 来源:发表于2018-07-09 18:01 被阅读1次

  用过express,koa,react(redux)的都会知道中间件,那么在这三个框架的中间件的实现有什么不同呢?

Express中间件

首先来看看express,分析express的源码可以看出express中router中间件和express是强耦合的,express把中间件的实现放在了router中去。
大概讲一下这里的中间件实现逻辑:

  1. 通过app.use收集中间件到stacks中去
  2. 有客户端请求时,遍历执行所有的中间件(把下一个中间件作为上一个中间件的next传入)

以下是这个逻辑的简单实现:

    var app = {
      stacks: [],
      // 收集中间件
      use: function () {
        var fns = arguments
        for (var i = 0, l = fns.length; i < l; i++) {
          this.stacks.push(fns[i])
        }
      },
      // 触发中间件
      handle: function (req, res) {
        var idx = 0,
            stacks = this.stacks;
        next()
        function next () {
          if (idx === stacks.length) {
            return;
          }
          var match = stacks[idx];
          idx++;
          match(req, res, next)
        }
      }
    }
    app.use(function (req, res, next) {
      console.log(0)
      next()
      console.log('00')
    }, function (req, res, next) {
      console.log(1)
      next()
      console.log(11)
    }, function () {
      console.log(2)
    })
    app.handle()
Koa中间件
    function compose (middleware) {
      return function (context, next) {
        // last called middleware #
        let index = -1
        return dispatch(0)
        function dispatch (i) {
          // 注释的部分为Koa源码,源码对async/await更加友好,为了简便对比,这里省略一些
          // if (i <= index) return Promise.reject(new Error('next() called multiple times'))
          index = i
          let fn = middleware[i]
          if (i === middleware.length) return Promise.resolve()
          // if (!fn) return Promise.resolve()
          // try {
          //   return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
          // } catch (err) {
          //   return Promise.reject(err)
          // }
          return fn(context, dispatch.bind(null, i + 1))
        }
      }
    }
    var app = {
      stacks: [],
      use: function () {
        var fns = arguments
        for (var i = 0, l = fns.length; i < l; i++) {
          this.stacks.push(fns[i])
        }
      },
      listen: function (...args) {
        // const server = http.createServer(this.callback())
        // return server.listen(...args)
        // 以下代码是为了方便调用中间件
        var cb = this.callback()
        cb()
      },
      callback: function () {
        var fn = compose(this.stacks)
        return fn
      }
    }
    app.use(async function(ctx, next) {
      console.log(1)
      await next()
      console.log(11)
    }, async function (ctx, next) {
      console.log(2)
      await next()
      console.log(22)
    }, async function (ctx, next) {
      console.log(3)
      await next()
      console.log(33)
    })
    app.listen()

中间件在Koa中的实现其实和Express没有本质的区别,逻辑基本上是一样的,多了一步compose,就是把中间件组合成一个函数。
说起Koa的中间件,很多地方都会提到洋葱模型,关于洋葱模型,按之前express的例子来说,就是按输出0,1,2,11,00的顺序执行,所以说洋葱模型并不是Koa特有的东西,另外,async/await也不是Koa才有的,async/await只是一个语法糖而已。
在我看来,Koa的中间件和Express的中间件区别在于Koa对异步中间件的处理可能更友好一些,从代码中的注释的源码部分可以看出。(对Koa没有实际的项目经验,仅就自己对源码的一些理解,有不对的地方希望可以不吝赐教)

Redux中间件

Redux中间件和这里使用的场景不同,这里我按Redux中间件的写法实现在node框架中的中间件。

    function compose (middleware) {
      return middleware.reduceRight((composed, f) => f(composed), () => {})
    }
    var app = {
      stacks: [],
      use: function () {
        var fns = arguments
        for (var i = 0, l = fns.length; i < l; i++) {
          this.stacks.push(fns[i])
        }
      },
      listen: function (...args) {
        // const server = http.createServer(this.callback())
        // return server.listen(...args)
        var cb = this.callback()
        cb()
      },
      callback: function () {
        var ctx = {request: {}, response: {}}
        var middlewares = this.stacks.map(middleware => middleware(ctx))
        var fn = compose(middlewares)
        return fn
      }
    }
    app.use(ctx => next => () => {
      console.log(1, ctx)
      next()
      console.log(11)
    }, ctx => next => () => {
      console.log(2, ctx)
      next()
      console.log(22)
    }, ctx => next => () => {
      console.log(3, ctx)
      next()
      console.log(33)
    })
    app.listen()

比较有意思的是compose函数的写法,利用es6,仅有一行代码就实现了。
这里是函数式编程中的currying,是一种使用匿名单参数函数实现多参数函数的方法。

相关文章

  • js中不同框架中间件实现的区别

      用过express,koa,react(redux)的都会知道中间件,那么在这三个框架的中间件的实现有什么不同...

  • Koa2 和 Express 中间件对比

    学习express和koa最主要是理解使用中间件,中间件是框架的核心实现,一起来看下这2个框架的中间件有什么区别。...

  • 知识点总结

    Koa2中间件 koa(面向node.js的表达式HTTP中间件框架)、koa-router(路由中间件)、koa...

  • Vue框架基础

    原生js与Vue框架的区别 用原生实现双向数据绑定 用Vue实现双向数据绑定 Vue是一个javaScript框架...

  • Category

    类别的作用?继承和类别在实现中有何区别? 类别主要有3个作用: (1)将类的实现分散到多个不同文件或多个不同框架中...

  • 快速搞懂从函数组合到中间件实现

    为了更好地解决业务逻辑中的对于AOP切面描述的需要,很多JS框架中都会用到中间件,怎么理解中间件结构呢,比较生动形...

  • 理解Redux中间件

    中间件是什么 如果你用过express.js之类的web框架,对中间件(Middleware)这个概念可能不会陌生...

  • 插件化之旅3-Hook实现加载完整的apk

    一、插件化与Hook实现集中式登录架构的区别? 不同点:目的不同,集中式登录框架是利用Hook实现的,插件化是实现...

  • NodeJS 中间件机制

    理解 Node.js 中间件机制核心代码的实现,加深对中间件机制的理解,有助于更好的使用和编写中间件。 一、中间件...

  • express及常用API

    核心就是中间件 概念 express 是TJ大神用Node.js封装的一个Web框架 核心概念是中间件 编程模型 ...

网友评论

    本文标题:js中不同框架中间件实现的区别

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