78 # koa 中间件的实现

简介: 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;

然后我们编写测试 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);

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

nodemon demo.js

目录
相关文章
|
前端开发 中间件
77 # koa 中间件的应用
77 # koa 中间件的应用
35 0
|
6月前
|
资源调度 JavaScript 前端开发
koa常用中间件
koa常用中间件
57 0
|
JSON 缓存 前端开发
koa 中间件
在写一个服务端应用的时候,一般都会使用到作为静态服务器,node 搭建静态服务请查看我以前文章,express中间件实现静态资源服务的话可以使用 express.static()来实现,那么koa如何实现呢? 其实对于一个静态服务的话,只要你会node这个底层的原理,express 或者 koa 这些上层应用都是基于底层原理来的
koa 中间件
|
中间件
Koa 中间件
Koa 中间件
139 4
Koa 中间件
|
JavaScript 前端开发 中间件
尝试理解 Koa、Redux middleware 的演进过程
最近开发 web 端,用的是 Egg node.js 框架,期间实现的一些功能例如:权限检测、操作日志上报等都是基于框架的 middleware 机制件完成的。虽然最后完成了功能,但其实对中间件真正的实现机制、运行时序还不能做到完全的理解。 Egg 是基于 Koa 实现的,Koa 的代码量非常少,加起来也就 1000 多行,涉及到中间件核心的部分,也就不到 100 行,如果有耐心可以直接读
91 0
|
JavaScript 前端开发 中间件
尝试理解 Koa、Redux middleware 的演进过程
最近开发 web 端,用的是 Egg node.js 框架,期间实现的一些功能例如:权限检测、操作日志上报等都是基于框架的 middleware 机制件完成的。虽然最后完成了功能,但其实对中间件真正的实现机制、运行时序还不能做到完全的理解。
100 0
|
中间件 数据库
多个koa中间件执行顺序
多个中间件执行顺序 多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行。 最外层的中间件首先执行。
2448 1
|
6月前
|
消息中间件 存储 负载均衡
消息中间件的选择:RabbitMQ是一个明智的选择
消息中间件的选择:RabbitMQ是一个明智的选择
112 0
|
5月前
|
消息中间件 存储 中间件
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
1415 0
|
4月前
|
消息中间件 编解码 Docker
Docker部署RabbitMQ消息中间件
【7月更文挑战第4天】Docker部署RabbitMQ消息中间件
277 3