简介
Koa是一个基于Node.js的Web框架,由Express.js的原作者设计和开发。它旨在提供一种更加简洁、灵活的方式来构建Web应用。Koa采用了异步、中间件和生成器等概念,让开发者能够更轻松地处理请求和响应、控制流程以及处理异步操作。
为什么选择koa
Koa是一个高效、灵活的Web框架,通过异步、中间件和生成器等概念,使得开发者能够更轻松地构建Web应用。它的简洁的语法和强大的功能使得Koa成为了Node.js生态系统中备受欢迎的选择。无论是处理HTTP请求、增加应用功能,还是改善代码组织和可维护性,Koa都能提供有力的支持。
所以,在我们以后做后端开发时都会选择这个框架,因为他很小很方便。
启动后端项目(启用web服务)
怎么去构建一个页面?我们首先需要初始化我们的后端项目
- 初始化目录,得到package.json文件夹
js
npm init -y
- 引入http模块
js
const http = require('http');
- 创建一个服务,可以向前端输出'Hello, World!'
js
const server = http.createServer((req, res) => {
res.end('Hello, World!')
});
- 监听服务,将服务运行在3000端口
js
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
- 打开我们的服务地址localhost:3000,发现后端确实在运行
启用koa,用koa启用web服务
- 安装koa依赖包
js
npm i koa
- 引入koa,得到实例对象
js
const Koa = require('koa');
const app = new Koa();
- 监听koa的实例对象
js
app.listen(3000, () => {
console.log('listening on port 3000');
})
向前端输出内容
定义你想要向web端输出的函数,并调用他
js
const main = (ctx) => {
// 在此处我们打印koa的上下文对象
console.log(ctx);
}
app.use(main)
分析koa的上下文对象
基础操作
- 向前端输出
js
const main = (ctx) => {
ctx.res.end('Hello World'); // 向前端输出
ctx.response.body = 'Hello Koa'; // 向前端输出,可以简化如下
ctx.body = 'Hello Koa!'; // 代理,省略中间对象
}
app.use(main)
代理操作
js
ctx.body = 'Hello Koa!';
- 判断类型后向前端输出
利用ctx.request.accepts
判断前后端响应头,对应发出不同信息
js
const main = (ctx) => {
if (ctx.request.header.accept === 'xml') {
ctx.body = '<data>hello koa</data>'
} else if (ctx.request.accepts('html')) {
ctx.body = '<data>hello world</data>'
}
}
- 请求路径
js
const main = (ctx) => {
console.log(ctx.req.url);
console.log(ctx.url); // 代理
}
app.use(main)
- 输出页面
- 引入fs模块,使用
fs.readFile()
读取文件 template.html中的内容向后端输出
js
const Koa = require('koa');
const app = new Koa();
const fs = require('fs');
const main = (ctx) => {
ctx.response.type = 'html'
const context = fs.readFileSync('./template.html', 'utf-8')
ctx.body = context
}
app.use(main)
app.listen(3000, () => {
console.log('listening on port 3000');
})
- fs还提供了第二种读取页面内容的方式------ 利用
createReadStream()
创造可读流
js
const Koa = require('koa');
const app = new Koa();
const fs = require('fs');
const main = (ctx) => {
ctx.type = 'html';
const context = fs.createReadStream('template.html')
console.log(context);
ctx.body = context;
}
app.use(main)
app.listen(3000, () => {
console.log('listening on port 3000');
})
这些都是koa的基本操作
配置路由,页面跳转
1. npm i koa-router
在上一篇章学习中我们通过 npm i koa
和 npm i koa-router
实现了不同路径跳转让我们再温习一遍。
在你的router文件中配置:
js
// 引入并调用
const router = require('koa-router')();
router.get('/', (ctx) => {
ctx.body = '<h1>首页</h1>'
})
router.get('/about', (ctx) => {
ctx.body = '<h1>关于</h1>'
})
// 抛出你配置的router
module.exports = router;
引入你配置的router:
js
const Koa = require('koa');
const app = new Koa();
const router = require('koa-router')();
app.use(router.routes())
app.listen(3000, () => {
console.log('原神启动');
})
这种方法需要新创建一个文件来配置路由和输出内容
2. npm i koa-route
在这里我们新介绍一种方法,在同一个文件中配置路由和内容。在node.js中输入指令 npm i koa-route
,在依赖包中引入。在这种方法中我们通过 ctx.type
向后端发送我们的数据类型,在 ctx.body
中写入需要传输的数据。使用app.use(router.get()) 配置路径和对应的函数。
在这里我们可以再定义一个函数记录并打印出当前HTTP请求的URL、请求方法(如GET、POST等)以及当前的时间戳。我这里就const一个logger,注意我们需要给这个函数传入参数next并且在函数中调用next()方法,只有这样才会使得该函数体被调用完成后还会继续执行下一个函数,而koa-route中内置了next方法,所以不用重复调用。
js
const Koa = require('koa');
const app = new Koa();
// 引入依赖包 koa-route
const router = require('koa-route');
const main = (ctx) => {
ctx.type = 'text/html';
ctx.body = '<h2>首页</h2>';
}
const about = (ctx) => {
ctx.type = 'html'
ctx.body = '<a href="/">点击去首页</a>'
}
const logger = (ctx, next) => {
// 记录HTTP请求的URL、请求方法以及当前的时间戳
console.log(`${ctx.url} - ${ctx.method} - ${Date.now()}`)
// 表示执行下一个中间件,剩下的app.use才会生效
next()
}
app.use(logger)
// 配置路径对应的函数
app.use(router.get('/', main))
app.use(router.get('/about', about))
// 监听端口
app.listen(3000, () => {
console.log('原神启动');
})
无论是 npm i koa-router
还是 npm i koa-route
,其实都是别人为我们造好的轮子,我们将这些轮子安装在我们的安装包中再遵照规则将他们引入,使用别人为我们打造好的方法。
在 npm | Home (npmjs.com) 中我们可以搜索到许多别人为我们封装好的方法,只要遵循文档去使用就能为我们的开发带来许多便捷。
洋葱模型
一、洋葱模型的概念
- 定义:洋葱模型是指中间件函数以类似洋葱的层次结构执行,即请求时从外层中间件进入,逐层向内,直到最内层中间件;响应时再从最内层中间件向外层逐层返回。
- 核心 :以
next()
函数为分割点,中间件在执行过程中,通过调用next()
函数将控制权交给下一个中间件,直到没有更多中间件可执行时,再从最后一个中间件开始逐层返回。
二、洋葱模型的实现原理
- 中间件注册 :通过
app.use()
方法注册中间件,这些中间件会被添加到一个中间件数组中,按照注册顺序执行。 - compose函数 :洋葱模型的核心是
compose
函数,它接收一个中间件数组作为参数,返回一个可以执行所有中间件的函数。这个函数通过递归调用每个中间件,实现了洋葱模型的执行流程。 - 递归调用 :在
compose
函数内部,通过递归调用dispatch
函数,实现了中间件的顺序执行和返回执行。每个中间件在执行时,都会调用dispatch
函数将控制权交给下一个中间件,直到最后一个中间件执行完毕,再从最后一个中间件开始逐层返回。
我们用一个小demo来理解洋葱模型和next()的运作
js
// 洋葱模型
const Koa = require('koa');
const app = new Koa();
// 一号中间件
const one = (ctx, next) => {
console.log(1);
next()
console.log(2);
}
// 二号中间件
const two = (ctx, next) => {
console.log(3);
next()
console.log(4);
}
// 三号中间件
const three = (ctx) => {
console.log(5);
console.log(6);
}
// `app.use()` 将中间件添加到应用的中间件栈中
app.use(one)
app.use(two)
app.use(three)
app.listen(3000, () => {
console.log('项目运行在端口 3000');
})
在上面这个例子中,在从上往下执行时遇到next()
时会直接跳转到下一个中间件,当没有更多中间件可执行时,再从最后一个中间件开始逐层返回。所以以上demo的输出结果是 " 1,3,5,6,4,2 "。