深入剖析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接口设计原理,结合代码详细的讲解了洋葱模型的实现原理

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

相关推荐
hackeroink34 分钟前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人6 小时前
前端知识补充—CSS
前端·css