深入剖析Koa接口封装原理,洋葱模型?递归调用?

前言

本文深入剖析Koa接口设计原理

讲解一下koa在封装接口时使用的洋葱模型以及洋葱模型实现原理递归调用

koa中间件式编程

Koa 中间件是一系列的函数,通过传递给 app.use() 的方式注册到应用程序中

每个中间件函数都会在请求或响应的某个阶段被执行,从而实现了对请求/响应生命周期的控制和扩展

我们看以下的代码

js 复制代码
const Koa = require("koa");

const app = new Koa();
const main = (ctx) => {
  console.log(ctx.url);
  if (ctx.url === "/") {
    ctx.response.type = "html";
    ctx.response.body = "首页";
  } else if (ctx.url === "/about") {
    ctx.response.type = "html";
    ctx.response.body = "关于";
  } else {
    ctx.response.type = "html";
    ctx.response.body = "404";
  }
};

app.use(main);

app.listen(3000, () => {
  console.log("http://localhost:3000");
});
  1. 引入 Koa 框架并创建一个新的 Koa 应用实例 app

  2. 定义了一个名为 main 的函数,它是一个中间件函数。这个函数接收 ctx 对象作为参数,ctx 对象包含了当前请求的上下文信息。

  3. main 函数中,根据不同的 URL 路径设置响应的类型和内容:

    • 如果访问根路径 /,返回 "首页" 字符串。
    • 如果访问 /about 路径,返回 "关于" 字符串。
    • 对于其他路径,返回 "404" 字符串。
  4. 使用 app.use(main)main 函数注册为中间件。这样,每次收到 HTTP 请求时,都会执行 main 函数来处理请求。

  5. 最后,调用 app.listen(3000, () => {...}) 在 3000 端口启动服务器,并在控制台输出 http://localhost:3000 提示访问地址。

可以看到在这段代码中main就相当于一个中间件,被koa框架给use了

文件响应

请求下载文件

  • 使用 fs.readFileSync("./template.html") 同步地读取 template.html 文件的内容,并将其赋值给 context 变量。
  • 打印 context 的内容到控制台。
  • context 的内容赋值给 ctx.body,将该内容作为响应返回给客户端
js 复制代码
const Koa = require("koa");
const fs = require("fs");

const app = new Koa();
const main = (ctx) => {
 
    const context = fs.readFileSync("./template.html");
    console.log(context);
    ctx.body = context;


};

app.use(main);

app.listen(3000, () => {
  console.log("http://localhost:3000");
});

这样实现的效果就是当我们去请求这个路径的时候会触发文件的下载

我们的文件内容为

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>hello world</h2>
    <h3>hello koa</h3>
</body>
</html>

可以看到打开下载的文件其内容就是这个

请求文件直接显示

如果我们希望使用html的方式去显示这段内容,我们需要再请求头的type字段指明一下,添加以下代码即可

js 复制代码
ctx.response.type = "html";

可以看到html被正确的显示出来了

koa-route 优雅的接口书写

前面提到的接口的书写方式并不是很优雅,通过不断地if-else去创建接口很不优雅

koa-route就将这个给进一步封装了,使得其书写的方式更加的优雅了

接下来我们引入koa-route

js 复制代码
npm i koa-route

引入到项目中使用

js 复制代码
const Koa = require("koa");
const Router = require("koa-route");

const app = new Koa();
const main = (ctx, next) => {
  ctx.response.type = "html";
  ctx.body = "<h2>首页</h2>";
  next();
};

const about = (ctx) => {
  ctx.response.type = "html";
  ctx.body = "<h2>关于</h2>";
};

app.use(Router.get("/", main));
app.use(Router.get("/about", about));

app.listen(3000, () => {
  console.log("http://localhost:3000");
});

可以看到这段代码将一个一个接口通过函数的方式进行了封装,并交给了koa

这样写代码就优雅了许多

这里面就涉及到了我们接下来要说的洋葱模型了

洋葱模型

为什么叫做洋葱模型呢?听我细细分析

我们首先看以下代码,猜测一下它的执行结果

js 复制代码
const Koa = require("koa");

const app = new Koa();

// 递归调用
// 洋葱模型
// 中间件
const one = (ctx, next) => {
  console.log(1);
  next();
  console.log(2);
};

const twe = (ctx, next) => {
  console.log(3);
  next();
  console.log(4);
};

const three = (ctx, next) => {
  console.log(5);
  console.log(6);
};

app.use(one);
app.use(twe);
app.use(three);

app.listen(3000, () => {
  console.log("http://localhost:3000");
});

执行结果为 135642

这就好像一个洋葱,每个中间件函数都可以在调用 next() 之前和之后执行一些操作,形成类似洋葱的结构

形成这个模型的原因就是因为它是用递归调用的

当执行到 one 中间件函数时:

  1. 首先打印出 "1"。
  2. 然后调用 next() 将控制权传递给下一个中间件 twe
  3. twe 中间件函数执行完毕并调用 next() 后,控制权又回到了 one 中间件函数。
  4. 此时 one 中间件函数继续执行,打印出 "2"。

当执行到 twe 中间件函数时:

  1. 首先打印出 "3"。
  2. 然后调用 next() 将控制权传递给下一个中间件 three
  3. three 中间件函数执行完毕后,控制权又回到了 twe 中间件函数。
  4. 此时 twe 中间件函数继续执行,打印出 "4"。

所以,整个执行顺序如下:

  1. 执行 one 中间件函数,打印 "1"。
  2. 执行 twe 中间件函数,打印 "3"。
  3. 执行 three 中间件函数,打印 "5" 和 "6"。
  4. 执行 twe 中间件函数,打印 "4"。
  5. 执行 one 中间件函数,打印 "2"。

总结

本文深入剖析Koa接口设计原理,结合代码详细的讲解了洋葱模型的实现原理

希望看到这里的你能够有所收获!!!

相关推荐
Myli_ing11 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维29 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
I_Am_Me_43 分钟前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
前端百草阁1 小时前
【TS简单上手,快速入门教程】————适合零基础
javascript·typescript
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue