Koa的学习

本节主要讲述Koa的学习

koa是由原express团队开发的一款更轻便好用的node web 应用框架。

一、安装

Koa要求node版本需要在7.6以上,所以使用前先node -v查询当前PC上的node版本。如果版本低于7.6,则需要升级后使用

1
2
#安装
npm i koa

二、基本使用

1
2
3
const Koa = require('koa')
const app = new Koa()
app.listen(3000)

2.1、context对象

Koa 提供一个 Context 对象,表示一次对话的上下文(包括 HTTP 请求和 HTTP 回复)。通过加工这个对象,就可以控制返回给用户的内容。

  • ctx.response 代表Http Response
  • ctx.request 代表Http Requeset
1
2
3
4
5
6
7
8
const Koa = require('koa')
const app = new Koa()

const main = ctx => {
ctx.response.body = 'hello world'
}
app.use(main)
app.listen(3000)
1
2
3
4
# 启动
node demo.js
# 浏览
localhost:3000

2.2、Http Response的类型

koa默认返回的类型为text/plain,如果想返回其他类型的内容,可以先用request.accepts判断一下,客户端希望接受什么数据(根据 HTTP Request 的Accept字段),然后使用ctx.response.type指定返回类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Koa =  require('koa')
const app = new Koa()

const main = ctx => {
if(ctx.request.accepts('xml')){
ctx.response.type='xml'
ctx.response.body='<data>这是一个xml</data>'
}else if(ctx.request.accepts('json')){
ctx.response.type = 'json'
ctx.response.body={data:'123'}
} else if (ctx.request.accepts('html')) {
ctx.response.type = 'html'
ctx.response.body='<p>了不起???</p>'
} else {
ctx.response.type = 'text'
ctx.response.body='hehe'
}
}

app.use(main)
app.listen(3000)
1
# 启动后访问,可以看到响应了xml

2.3 网页模板

实际开发中,返回给用户的网页往往都写成模板文件。我们可以让 Koa 先读取模板文件,然后将这个模板返回给用户。

1
2
3
4
5
6
7
8
9
10
const Koa = require('koa')
const fs = require('fs')
const app = new Koa()

const main = ctx => {
ctx.response.type = 'html'
ctx.response.body = fs.createReadStream('./index.html')
}
app.use(main)
app.listen(3000)

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>

<body>
<div id="root">
Koa
</div>
</body>

</html>

路由koa-route

原生路由用起来不太方便,可以使用封装好的koa-route模块

  1. 引入koa-route (npm i koa-route -S)
  2. 创建响应
  3. 设置响应路由 app.use(route.get(‘/‘,main))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const route = require('koa-route')
const Koa=require('koa');
var app=new Koa();

const about = ctx => {
ctx.response.type = 'html'
ctx.response.body = '<h1>这是另一页</h1><a href="/"> 返回首页</a> '
}
const main = ctx => {
ctx.response.body='<h1>这是首页</h1>'
}
app.use(route.get('/',main))
app.use(route.get('/about',about))

app.listen(3001);

2.1 静态资源

如果网站提供静态资源(图片、字体、样式表、脚本……),为它们一个个写路由就很麻烦,也没必要。koa-static模块封装了这部分的请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 目录结构
|_ static
|_ 01.jpg
|_ 01.js

# 01.js服务文件
const serve = require('koa-static')
const Koa = require('koa')
const app = new Koa()

const main = serve('static') //相对路径
const main = serve(__diraname+'/static') //绝对路径
app.use(main)
app.listen(3000)

# 浏览器访问
localhost:3000/01.jpg

2.2 重定向

服务器需要重定向(redirect)访问请求。比如,用户登陆以后,将他重定向到登陆前的页面。ctx.response.redirect()方法可以发出一个302跳转,将用户导向另一个路由。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const Koa=require('koa');
const app=new Koa();
const route=require('koa-route');

const about=ctx=>{
ctx.response.redirect('/');
}

const main=ctx=>{
ctx.response.body = "<h1>这是首页</h1>"
}

app.use(route.get('/',main));
app.use(route.get('/about',about))
app.listen(3001);

中间件

Koa 的最大特色,也是最重要的一个设计,就是中间件(middleware)

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const Koa=require('koa');
const app=new Koa();

const logger = (ctx,next)=>{
console.log("中间件的运行")
}

const main = ctx=>{
ctx.response.body = "呵呵"
}

//中间件
app.use(logger);
app.use(main);
//中间件

app.listen(3002);
  • 以上的logger函数,main函数就是一个中间件middleware,因为它处在http requestresponse之间,用来实现某种中间功能
  • app.use(middleWare) 来使用中间件
  • 参数:默认接受2个参数 (ctx,next),ctx为context对象,当执行完中间件的功能后,调用next()将执行权交移给下一个中间件

中间件栈

多个中间件会形成一个栈结构(middle stack),以”先进后出”(first-in-last-out)的顺序执行。

1
2
3
4
5
6
7
1. 最外层的中间件首先执行。 
2. 调用next函数,把执行权交给下一个中间件。
3. ...
4. 最内层的中间件最后执行。
5. 执行结束后,把执行权交回上一层的中间件。
6. ...
7. 最外层的中间件收回执行权之后,执行next函数后面的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const Koa=require('koa');
const app=new Koa();

const one = ((ctx,next)=>{
console.log('one->');
next();
console.log('<-one')
})

const two = ((ctx,next)=>{
console.log('2->');
next();
console.log('<-2')
})

app.use(one);
app.use(two);

app.listen(3003);
1
2
3
4
5
# 执行结果
one->
2->
<-2
<-one
  • 如果不调用next(),则不会移交执行权

错误处理

如果代码运行过程中发生错误,我们需要把错误信息返回给用户。HTTP 协定约定这时要返回500状态码。Koa 提供了ctx.throw()方法,用来抛出错误,ctx.throw(500)就是抛出500错误

1
2
3
4
5
6
7
8
9
10
11
12
const Koa = require('koa')
const compose = require('koa-compose')
const app = new Koa()

const main = (ctx, next) => {
ctx.throw(500)
}

app.use(main)
app.listen(3000)
# 访问
internal server error