75 # koa 基本逻辑实现以及属性的扩展

准备工作

新建自己的 kaimo-koa 文件夹,结构如下:

  • lib
    • application.js:创建应用
    • context.js:上下文
    • request.js:koa 中自己实现的 request 的对象
    • response.js:koa 中自己实现的 response 的对象
  • package.json:里面需要注意 main 字段,我们需要将 lib/application.js 作为入口
{
    "name": "kaimo-koa",
    "version": "1.0.0",
    "description": "",
    "main": "lib/application.js",
    "directories": {
        "lib": "lib"
    },
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC"
}

75 # koa 基本逻辑实现以及属性的扩展_第1张图片

ctx 是什么东西?

ctx 中整合了 request 和 response,req 以及 res

  • koa 自己实现的 request 和 response
  • http 原生的 req 以及 res

ctx.request.req.urlctx.req.url 是等价的

ctx.path 就是去 ctx.request.path 上取的,ctx.request 内部使用了 url 模块进行解析

代码实现基本的逻辑以及属性的扩展

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);
    }
    use(callback) {
        this.callback = 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;
        return ctx;
    }
    handleRequest(req, res) {
        const ctx = this.createContext(req, res);
        this.callback(ctx);
    }
    listen(...args) {
        const server = http.createServer(this.handleRequest.bind(this));
        server.listen(...args);
    }
}

module.exports = Application;

request.js:koa 中自己实现的 request 的对象,进行属性扩展

const url = require("url");
const request = {
    // 属性访问器的方式 ctx.request.url 就会执行 url()
    get url() {
        // this 就是 ctx.request
        return this.req.url;
    },
    get path() {
        return url.parse(this.req.url).pathname;
    },
    get query() {
        return url.parse(this.req.url).query;
    }
    // ... 可以自己添加其他的扩展属性
};

module.exports = request;

编写 demo.js 测试

const Koa = require("./kaimo-koa");
const app = new Koa();

app.use(async (ctx, next) => {
    ctx.body = "Hello kaimo Koa";
    console.log("url---->", ctx.request.url);
    console.log("path---->", ctx.request.path);
    console.log("query---->", ctx.request.query);
});

app.on("error", (err) => {
    console.log(err);
});

app.listen(3000);

启动服务后访问 http://localhost:3000/kaimo?a=313

nodemon demo.js

75 # koa 基本逻辑实现以及属性的扩展_第2张图片

你可能感兴趣的:(Node,/,Node,框架,前端工程架构,koa)