简介
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。
准备
首先,检查 Node 版本。
$ node -v
v8.0.0
Koa 必须使用 7.6 以上的版本。如果你的版本低于这个要求,就要先升级 Node。
准备好之后我们在本地建一个hell-world文件,然后通过npm install koa安装koa。 我们在项目根目录下创建一个app.js
// 1.引入koa
const Koa = require('koa')
// 2.创建koa实例
const app = new Koa()
// 3.创建一个中间件,所有的请求都会执行到这个中间件处理
// ctx是koa提供的上下文对象。(包含请求和对应的响应,通过加工这个对象就可以控制返回个用户的信息)
// ctx.request 请求 ctx.respond 响应
app.use(async (ctx) =>{
// 设置响应体
ctx.response.body = 'Hello World'
})
// 4.启动koa
app.listen(3000,()=>{
console.log('请访问 http://localhost:3000');
})
我们在终端通过 node app.js启动一下项目,然后访问 http://localhost:3000 就可以看到打印的内容了。这样一个简单的应用程序就创建好了
koa中处理get请求
前面的步骤都是一样的,安装koa,然后导入创建koa实例,准备中间件。当我们打开页面之后在 http://localhost:3000/?username=zhangsan&age=18 拼接上参数之后,我们刷新页面,发现终端并没有反应,这个时候我们对中间件部分进行一个配置,通过ctx.request就可以接收到在url里面拼接的内容
当我们想拿到拼接的参数时可以通过ctx.request.query来获取。
// 1.引入koa
const Koa = require('koa')
// 2.创建koa实例
const app = new Koa()
// 3.创建一个中间件,所有的请求都会执行到这个中间件处理
// ctx是koa提供的上下文对象。(包含请求和对应的响应,通过加工这个对象就可以控制返回个用户的信息)
app.use(async (ctx) =>{
// ctx.request 请求 ctx.response 响应
// 通过query或者querystring来获取传过来的参数。
// query是查询参数, 对象格式;querystring也是查询参数, 字符串格式。
console.log(ctx.request.query);
// 设置响应体
ctx.response.body = 'Hello Wo rld'
})
// 4.启动koa
app.listen(3000,()=>{
console.log('服务器启动成功');
})
koa处理post请求
获取post请求发送的请求题参数,相对较为繁琐,大致思路为:
- 监听node.js原生请求对象的data事件,从请求体中获取数据,并将所有数据拼合起来(因为如果请求体中携带的数据量比较大,就会分几次来触发data事件,逐步获取)
- 监听node.js原生请求对象的end事件,获知请求体数据被完全获取
// 引入koa
const Koa = require('Koa')
// 创建koa实例
const app = new Koa()
// 中间件
app.use((ctx)=>{
// ctx.req ctx.res 这个是原生nodejs的
// ctx.request ctx.response 这个是koa内置的
let paramsStr = ''
// 监听原生node.js request对象的 data事件
// 每次有数据过来,都会触发一次data,数据量大一次请求会触发多次data事件
ctx.req.on('data',(data)=>{
paramsStr += data
})
//监听原生nodejs request对象的end事件
// 一旦请求所有的数据接收完成就会触发end事件
ctx.req.on('end',()=>{
console.log(paramsStr,'结束');
})
})
app.listen(3000,()=>{
console.log('启动成功');
})
之后当我们以同样的方式在浏览器输入http://localhost:3000的时候会发现页面提示 Not found,因为只有get请求可以通过这种方式,如果是post请求的话我们可以通过postman来进行测试。其中针对post请求返回的参数我们还可以通过URLSearchParams对其进行处理,比如
ctx.req.on('end',()=>{
console.log(paramsStr,'结束');
// { 'username' => 'zs', 'age' => '25' }
// params.get(key)传入username就可以得到zs,传入age就可以得到18
// params.has(key)是根据键来判断是否存在
// params.keys()获取到所有键
const params = new URLSearchParams(paramsStr)
console.log(params,'params=====>');
console.log(params.get('age'));
console.log(params.has('age'));
console.log(params.keys());
})
})
响应一个页面
我们引入nodejs中的fs读文件模块,用来读取html页面。
// 响应页面
const Koa = require('Koa')
const fs = require('fs')
const path = require('path')
const { join } = require('path')
const app = new Koa()
app.use((ctx)=>{
// __dirname找当前文件的绝对路径
fs.readFile(join(__dirname,'test.html'),(err,data)=>{
if(err){
return console.log(err);
}
// 读取的数据是buffer格式的,需要用toString转换格式
console.log();
ctx.response.body = `data.toString()`
})
})
app.listen(8000,()=>{
console.log('success!!');
})
但是这个时候我们会发现在浏览器打开的时候会提示Not Found,这是因为在读文件这个流程结束之前就已经执行了ctx.response.body = data.toString()这个操作,所以我们如果想要成功读取到html文件,我们需要把它阻塞,这里我们对函数进行一下封装:
// 响应页面
const Koa = require('Koa')
const fs = require('fs')
const path = require('path')
const { join, resolve } = require('path')
const { rejects } = require('assert')
const app = new Koa()
// 封装一读取html的函数 return 一个promise对象
function getHtmlFile(filePath) {
return new Promise((resolve,reject)=>{
// __dirname找当前文件的绝对路径
fs.readFile(join(__dirname,filePath),(err,data)=>{
if(err){
return reject(err);
}
// 读取的数据是buffer格式的,需要用toString转换格式
resolve(data.toString())
// ctx.response.body = await 读取文件的 内容
})
})
}
app.use(async ctx=>{
ctx.body = await getHtmlFile('./test.html') //这里通过await对他进行阻塞
})
app.listen(8000,()=>{
console.log('success!!');
})
koa中处理静态资源
基本上和读取html页面一样,引入fs然后封装一个函数,不过需要注意的是,读取图片的时候要设置响应头!
// 响应页面
const Koa = require('Koa')
const fs = require('fs')
const path = require('path')
const { join, resolve } = require('path')
const { rejects } = require('assert')
const app = new Koa()
// 封装一个读取静态资源图片的函数
function getImageFile(filePath){
return new Promise((resolve,reject)=>{
fs.readFile(join(__dirname,filePath),(err,data)=>{
if(err){
return reject(err)
}
// 这里要保持buffer数据格式
resolve(data)
})
})
}
app.use(async ctx=>{
// 重要:需要特别设置静态资源文件(图片)的content-type 响应头
// 否则在浏览器中只会下载文件
ctx.set('Content-type','image/png')
ctx.body = await getImageFile('./koa.png')
})
app.listen(8000,()=>{
console.log('success!!');
})