Koa2初体验(一)

一、起步

首先创建一个文件夹,然后初始化 package.json :

1
npm init -y

安装koa2:

1
cnpm i koa --save

在文件目录下新建一个index.js,然后写下如下代码:

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

app.use( async(ctx) => {
ctx.body = "hello world"
})
app.listen(1996)
console.log("demo in run")

. aa
然后运行这个文件:

1
nodemon index.js

然后我们就能在后台看见这个:

1
demo is run

然后打开浏览器,输入 :http://127.0.0.1:1996 就可以看见这个了:

输入图片说明

这样我们就搭建好了最简单的web服务器。但除了这些,有一点需要知道的是,在koa2中,async函数已经大规模使用了,它很好的处理了异步的逻辑,所以学习koa2之前,尽量将async和await解决掉:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const wait1 = () => {
return new Promise(resolve => {
resolve(setTimeout(() => {console.log("1s later")}, 1000))
})
}

const wait2 = () => {
return new Promise((resolve) => {
resolve(setTimeout(()=>{console.log("2s later")},2000))
})
}
async function test() {
const a = await wait1()
const b = await wait2()
console.log("end")
}
console.log("start")
test()

上面的代码执行起来就是这样的:

1
2
3
4
start
end
1s later
2s later

它很好的解决了异步的一些麻烦,且写出来的代码的可读性也非常好。

二、请求数据获取

2.1 Get请求的接收

在Koa2中GET请求可以通过 request 接受收,但接受的方式有两种:

  • query:返回的是格式化后的参数对象
  • querystring:返回的请求字符串

我们可以由两种方式来获取GET请求,一种是通过 ctx.request 来获取GET请求,一种则是直接在ctx中得到GET请求:

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

app.use(async(ctx) => {
const url = ctx.url
// 使用 ctx.request
const request = ctx.request
const req_query = request.query
const req_querystring = request.querystring
// 直接使用ctx来获取
const req_ctx = ctx.query
const req_ctx1 = ctx.querystring
ctx.body = {
url,
req_query,
req_querystring,
req_ctx,
req_ctx1,
}

})
app.listen(3000,() => {
console.log("demo1 is run")
})

然后我们在浏览器中输入 http://127.0.0.1:3000?user=srtian&age=18 来访问页面就可以看到这个(这是经过美化的表现):
输入图片说明

2.2 POST请求的接收

在 Koa2 中,没有给对于 POST 请求的处理封装方便的获取参数的方法,需要通过通过解析上下文 context 中的元素 node.js 请求对象 req 来获取。因此获取POST请求的步骤可以理解为以下三步:

  1. 解析上下文 ctx 中的原生 node.js 对象 req。
  2. 将POST表单数据解析成 query string 字符串。
  3. 将字符串转换成 JSON 格式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const Koa = require('koa')
const app = new Koa()

app.use(async(ctx) => {
if (ctx.url === '/' && ctx.method === 'GET') {
let html = `
<h2>This is demo2</h2>
<form method="POST" action="/">
<p>username:</p>
<input name="username">
<p>age:</p>
<input name="age">
<p>website</p>
<input name="website">
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if (ctx.url === '/' && ctx.method === 'POST') {
let postData = await parsePostDate(ctx)
ctx.body = postData
} else {
ctx.body = '<h2>404</h2>'
}
})

const parsePostDate = (ctx) => {
return new Promise((resolve, reject) => {
try{
let postData = ""
ctx.req.on('data', (data) => {
postData += data
})
ctx.req.addListener("end", function() {
let parseData = parseQueryStr(postData)
resolve(parseData)
})
} catch(error) {
reject(error)
}
})
}

const parseQueryStr = (queryStr) => {
const queryData = {}
const queryStrList = queryStr.split('&')
console.log(queryStrList)
for (let [index,queryStr] of queryStrList.entries()) {
let itemList = queryStr.split('=')
console.log(itemList)
queryData[itemList[0]] = decodeURIComponent(itemList[1])
}
return queryData
}

app.listen(3000, () => {
console.log('dom2 is run')
})

然后打开浏览器,输入http://127.0.0.1:3000/:
输入图片说明

完善信息后,点击submit:

输入图片说明

koa-bodyparser中间件

显然上面的 POST 请求的接受非常麻烦,至少对我而言,徒手写个这样的轮子在不查资料的情况下是做不到的,而这样的轮子当然也有人来做,koa-bodyparser就是一个造好的轮子。我们在koa中把这种轮子就叫做中间件。对于POST请求的处理,koa-bodyparser中间件可以把koa2上下文的formData数据解析到ctx.request.body中。

首先我们要安装中间件:

1
cnpm i koa-bodyparser@3 --save

然后我们就能非常轻松愉快的使用这个中间件来改造我们上面的代码了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const Koa  = require('koa')
const ap3p = new Koa()
const bodyParser = require('koa-bodyparser')

app.use(bodyParser())

app.use(async(ctx) => {
if (ctx.url === '/' && ctx.method === 'GET') {
let html = `
<h2>This is demo2</h2>
<form method="POST" action="/">
<p>username:</p>
<input name="username">
<p>age:</p>
<input name="age">
<p>website</p>
<input name="website">
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if (ctx.url === '/' && ctx.method === 'POST') {
let postData = ctx.request.body
ctx.body = postData
} else {
ctx.body = '<h2>404</h2>'
}
})



app.listen(3000, () => {
console.log('demo2 is run')
})