美文网首页
express 和 koa

express 和 koa

作者: 看到这朵小fa了么 | 来源:发表于2020-03-31 10:05 被阅读0次

    express

    • req.cookies cookie-parser 处理cookie挂载
    • req.query, req.body拦截请求参数
    • express.json() 转化json (解析json格式的请求参数,赋值到req.body,返回参数json格式)
    • express.urlencoded() 解析req 其他格式的数据
    • express-session connect-redis
    • morgan 输出日志 通过文件流写入日志(flags: 'a') ,配置参数:https://github.com/expressjs/morgan
    • router=express.Router()
    • app.use(命中, 回调中间件)

    中间件

    • 中间件用于帮助我们做一些繁琐的基本工作,如路由匹配(koa-router),参数提取(koa-bodypaser),响应json数据(koa-json),支持跨域(koa-cors),保持用户登录状态(koa-session/koa-jwt)
    • 中间件的设计,专注于解决一个问题,通过中间件的组合来实现功能的拓展
    • 中间件运行,尾调用的洋葱模型

    express和koa的区别

    • koa不在内核中绑定任何中间件,express则内置了一些功能如express.Router()
    • koa原生支持async await 相比于promise处理异步回调更加优雅
    • 最重要的是两者对异步的中间件调用顺序是不同的,express不会等待中间件的异步处理执行完毕,主要是由于内部是通过回调函数的组合,其next的机制导致不会等待异步的完成而继续执行同步操作,当然对于一个中间件的内部使用了async await,执行顺序还是正确的;
      而koa它的next机制是利用闭包和递归的性质,一个个执行中间件,并且每次执行都是返回promise的封装,再结合generator状态机,实现同步异步的按顺序执行

    中间件的实现

    • express
      脚手架:express
      1、分解来看 有use get post方法可以注册路由 listen进行监听
      2、注册路由时需要对参数进行匹配,分解为path和对应的中间件列表作为对象存储
      3、listen监听注册回调函数处理中间件
      4、中间件的收集需要匹配方法和路径
      6、中间件的触发,需要调用next函数进行依次触发
      7、repress-session; require('connect-redis')(session)
    • koa
      koa1 用generator实现
      koa2 async await实现 结合node8+支持 实现更加完美
      脚手架 npm i koa-generator; koa2初始化
      1、koa-router; router.prefix(/)
      2、中间件必须以async开头,保证next执行顺序,通过await等待异步的执行
      3、ctx封装了request和response
      3、返回值可以直接赋值给ctx.body 不需要处理json格式和异步回调promise返回
      4、koa-generic-session koa-redis
      5、实现koa无需考虑路径匹配,主要在于回调函数的处理,需要对中间件进行promise的包装,保证执行顺序
      6、ctx的参数包装
    // 简单实现express
    
    const http = require("http");
    const slice = Array.prototype.slice;
    
    class LikeExpress {
      constructor() {
        this.routes = {
          all: [],
          get: [],
          post: []
        };
      }
    
      register() {
        let info = {};
        if (typeof arguments[0] === "string") {
          info.path = arguments[0];
          info.stack = slice.call(arguments, 1);
        } else {
          info.path = "/";
          info.stack = slice.call(arguments, 0);
        }
        return info;
      }
      use() {
        let result = this.register.apply(this, arguments);
        this.routes.all.push(result);
        console.log('all', this.routes.all)
      }
      get() {
        let result = this.register.apply(this, arguments);
        this.routes.get.push(result);
      }
      post() {
        let result = this.register.apply(this, arguments);
        this.routes.post.push(result);
      }
      match(method, url) {
        
        let resultList = [];
        let stack = [];
        stack = stack.concat(this.routes.all);
        stack = stack.concat(this.routes[method]);
        if (url === "favicon.icon") {
          return resultList;
        }
        for (let item of stack) {
          if (item.path.indexOf(url) === 0) {
            resultList = resultList.concat(item.stack);
          }
        }
        console.log('resut', resultList)
        return resultList;
      }
      handler(req, res, list) {
        const next = () => {
          let middleware = list.shift();
          if (typeof middleware === 'function') {
            middleware(req, res, next);
          }
        };
        next();
      }
      callback() {
        return (req, res) => {
          res.json = (data) => {
            res.setHeader("Content-type", "application/json");
            res.end(JSON.stringify(data));
          };
          let url = req.url;
          let method = req.method.toLowerCase();
          let resultList = this.match(method, url);
          console.log('list', resultList)
          this.handler(req, res, resultList);
        };
      }
      listen(...args) {
        let server = http.createServer(this.callback());
        server.listen(...args);
      }
    }
    
    module.exports = () => {
      return new LikeExpress();
    };
    
    // 简单koa2实现 主要是promise对象的包装
    const http = require("http");
    
    // 组合中间件
    function compose(middlewareList) {
        return function(ctx) {
            function dispath(i) {
               const fn = middlewareList[i]
               try {
                   return Promise.resolve(
                       fn(ctx, dispath.bind(null, i+1))
                   )
               } catch (err) {
                   return Promise.reject(err)
               }
            }
            return dispath(0)
        }
    }
    class LikeKoa2 {
      constructor() {
        this.middlewareList = [];
      }
    
      use(fn) {
        this.middlewareList.push(fn);
        return this;
      }
      createContent(req, res) {
          const ctx = {
              req, res
          }
          ctx.query = req.query
          return ctx
      }
      handler(ctx, fn) {
          return fn(ctx)
      }
      callback() {
          const fn = compose(this.middlewareList)
          return (req, res, next)=> {
             const ctx = this.createContent(req, res)
             return this.handler(ctx, fn)
          }
      }
      listen(...args) {
        let server = http.createServer(this.callback());
        server.listen(...args);
      }
    }
    
    module.exports = () =>{
        return new LikeKoa2()
    }
    
    
    

    相关文章

      网友评论

          本文标题:express 和 koa

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