koa

作者: 9吧和9说9话 | 来源:发表于2020-03-08 17:53 被阅读0次

koa的处理流程

koa的处理流程

koa的中间件

const Koa = require('koa');
const app = new Koa();

// logger

app.use(async (ctx, next) => {
  await next();// 将控制权交给下一个中间件
  const rt = ctx.response.get('X-Response-Time');
  console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});

// x-response-time

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();// 将控制权交给下一个中间件
  const ms = Date.now() - start;
  ctx.set('X-Response-Time', `${ms}ms`);
});

// response

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

洋葱模型实现

  1. 通过await next();进入下一个中间件
  2. nextcompose中定义的dispatch

关键代码 compose的实现

function compose (middleware) {
  if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
  for (const fn of middleware) {
    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
  }

  /**
   * @param {Object} context
   * @return {Promise}
   * @api public
   */

  return function (context, next) {
    // last called middleware #
    let index = -1
    return dispatch(0)
    // dispatch 就是包装我们的中间件
    function dispatch (i) {
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
        // 这里是执行我们添加的每一个中间件的时机
        // 并且next 就是dispatch 
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
}

最终我们开始部分的代码中间件执行顺序如下(伪代码)

// middlewares 
一个请求达到之后
执行中间件 fn0(ctx, next)
fn0 ---> 
  前半段
  await next()---> 交出控制权(通过generator实现的协程实现),执行fn1


fn1 ---> 
  前半段
  await next()---> 交出控制权(通过generator实现的协程实现),执行fn2

fn2 ---> 
  前半段
  后半段

恢复控制权---> fn1 
  await next()---> 交出控制权(通过generator实现的协程实现),执行fn2
 ----> 恢复(上面的await 赋值操作也会执行)
  后半段

恢复控制权---> fn2
  await next()---> 交出控制权(通过generator实现的协程实现),执行fn2
 ----> 恢复(上面的await 赋值操作也会执行)
  后半段

这就是


洋葱模型

既然compose如此重要,先看下javascript中的compose

compose 函数式编程中一个重要的使用

通过组合不同的功能达到最终的实现。

  1. 问题

  2. 代码实现

// undercore中的实现
_.compose = function() {
    var args = arguments;
    var start = args.length - 1;
    // 返回一个函数
    return function() {
      var i = start;
      // 从后向前执行 每一个函数,并且将返回值记录
      var result = args[start].apply(this, arguments);
      while (i--) result = args[i].call(this, result);
      return result;
    };
  };
  1. 作用
    (1)分解任务
    (2)函数式编程中的复用和扩展性的实现
    (3)数据流管道

函数柯里化 curry

  1. 问题

  2. 解决 (curry实现)

function curry(fn, length) {
    let args = [];
    length = length|| fn.length;
    return function inner(...arg) {
        args = args.concat(arg);
        if(length) {
            if(args.length<length) {
                // console.log('inner');
                return inner;
            } else {
                return fn.apply(null, args)
            }
        }
    }
}
  1. 作用
    (1)参数预设(缓存)
    (2)延时函数执行时机
    (3)分解任务
    (4)将多参数版本改成单参数版本 供compose消费

参考:

  1. 阮一峰老师的函数式编程教程
  2. 函数式编程教程
  3. compose vs curry

相关文章

  • koa2 用到的中间件

    koa-router //koa路由 koa-bodyparser //post 获取值 koa-stat...

  • koa-router处理URL

    koa-router处理URL koa-router使用的结构const Koa = require('koa')...

  • koa 自学入门

    const Koa = require('koa');const route = require('koa-rou...

  • 初见 Koa 2

    koa 和 koa 2 最大的不同是koa 2 支持 async/await。koa 通过结合 generato...

  • trello01:后端搭建

    开发依赖: koa : 后端的主框架。 koa-router:基于Koa的路由。 koa-static-cache...

  • Koa2教程(常用中间件篇)

    目录一、koa-bodyparser二、koa-router三、koa-views + ejs四、koa-stat...

  • koa2设置跨域

    npm install --save koa2-corsvar Koa = require('koa');var ...

  • koa

    koa 学习 中间件 koa-router koa-router 获取get/post请求参数 koa-bodyp...

  • koa2 入门教程

    koa koa 中文koa-generator 简介 koa 是一个新的 web 框架, 由 express 原班...

  • UMI 服务端渲染

    Umi 开启服务端渲染: 安装 koa、koa-compress、 koa-mount、koa-static、ko...

网友评论

      本文标题:koa

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