• 78 # koa 中间件的实现


    上上节实现了上下文的,上一节使用了一下中间件,这一节来实现 koa 的中间件这个洋葱模型。

    思路:

    • 储存用户所有的 callback
    • 将用户传递的 callback 全部组合起来(redux 里的 compose)
    • 组合成一个线性结构依次执行,组合完返回一个大的 promise
    • 当组合后的 promise 完成后,拿到最终的结果响应回去

    application.js 代码实现如下:核心就是组合方法的实现

    const EventEmitter = require("events");
    const http = require("http");
    const context = require("./context");
    const request = require("./request");
    const response = require("./response");
    
    console.log("kaimo-koa---->");
    
    class Application extends EventEmitter {
        constructor() {
            super();
            // 防止多个实例共享 context request response 需要进行拷贝
            this.context = Object.create(context);
            this.request = Object.create(request);
            this.response = Object.create(response);
            // 储存用户所有的 callback
            this.middlewares = [];
        }
        use(callback) {
            // 将用户传递的 callback 全部组合起来
            this.middlewares.push(callback);
        }
        // 创建一个上下文
        createContext(req, res) {
            // 每次请求都应该是一个全新的 context,需要拷贝
            let ctx = Object.create(this.context);
            // 上下文中有一个 request 对象,是自己封装的
            ctx.request = Object.create(this.request);
            // 上下文中还有一个 req 属性 指代的是原生的 req,自己封装的 request 对象上有 req 属性
            ctx.req = ctx.request.req = req;
            // 上下文中还有一个 response 对象,是自己封装的
            ctx.response = Object.create(this.response);
            // 上下文中还有一个 res 属性 指代的是原生的 res,自己封装的 response 对象上有 res 属性
            ctx.res = ctx.response.res = res;
            return ctx;
        }
        compose(ctx) {
            // 在数组中取出第一个,第一个执行后执行第二个
            const dispatch = (i) => {
                if (i === this.middlewares.length) return Promise.resolve();
                let middleware = this.middlewares[i];
                // 中间件如果不是 async 需要 Promise 包装一下,() => dispatch(i + 1) 就是 next
                return Promise.resolve(middleware(ctx, () => dispatch(i + 1)));
            };
            return dispatch(0);
        }
        async handleRequest(req, res) {
            const ctx = this.createContext(req, res);
            // 组合成一个线性结构依次执行,组合完返回一个大的 promise
            await this.compose(ctx);
            // 当组合后的 promise 完成后,拿到最终的结果响应回去
            let body = ctx.body;
            res.end(body);
        }
        listen(...args) {
            const server = http.createServer(this.handleRequest.bind(this));
            server.listen(...args);
        }
    }
    
    module.exports = Application;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    然后我们编写测试 demo.js

    const Koa = require("./kaimo-koa");
    
    const app = new Koa();
    
    const log = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("kaimo313");
                resolve();
            }, 3000);
        });
    };
    
    app.use(async (ctx, next) => {
        console.log(1);
        console.time("kaimo");
        await next();
        ctx.body = "hello 1";
        console.log(2);
        console.timeEnd("kaimo");
    });
    
    app.use(async (ctx, next) => {
        console.log(3);
        await log();
        ctx.body = "hello 2";
        await next();
        console.log(4);
    });
    
    app.use(async (ctx, next) => {
        console.log(5);
        ctx.body = "hello 3";
        await next();
        console.log(6);
    });
    
    app.listen(3000);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    启动服务,访问 http://localhost:3000/

    nodemon demo.js
    
    • 1

    在这里插入图片描述

  • 相关阅读:
    回溯算法解决N皇后问题以及个人理解
    nginx配置负载均衡--实战项目(适用于轮询、加权轮询、ip_hash)
    Android Material Design
    HTML5七夕情人节表白代码 (动态3D相册) HTML+CSS+JS
    娄底医药工业洁净厂建设基本要点概述
    AI在创造还是毁掉音乐?
    【PyQt学习篇 · ⑨】:QWidget -控件交互
    array.form()详解
    CSS魔术师Houdini,用浏览器引擎实现高级CSS效果
    【JavaScript】运算符与表达式、控制语句、常用API
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/132703122