koa2开始
async/await 使用
快速上手理解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function getSyncTime() {
return new Promise((resolve, reject) => {
try {
let startTime = new Date().getTime()
setTimeout(() => {
let endTime = new Date().getTime()
let data = endTime - startTime
resolve( data )
}, 500)
} catch ( err ) {
reject( err )
}
})
}
async function getSyncData() {
let time = await getSyncTime()
let data = `endTime - startTime = ${time}`
return data
}
async function getData() {
let data = await getSyncData()
console.log( data )
}
getData()
从代码中可以找到
异步->同步 底层返回一个promise 可以替代callback
koa 结构
https://github.com/koajs/koa/
开源中的源码结构1
2
3
4
5
6├── lib
│ ├── application.js
│ ├── context.js
│ ├── request.js
│ └── response.js
└── package.json
application 核心中间件处理流程。入口文件
context 上下文
request http 请求
response 处理http响应
koa2特性
只提供封装好http上下文,请求,响应,以及基于async/await的中间件容器
koa中间件开发
async 中间件开发1
2
3
4
5
6
7
8
9function log( ctx ) {
console.log( ctx.method, ctx.header.host + ctx.url )
}
module.exports = function () {
return async function ( ctx, next ) {
log(ctx);
await next()
}
}
koa原生路由实现
1 | const Koa = require('koa') |
koa-router
https://github.com/ChenShenhai/koa2-note/tree/master/demo/route-use-middleware1
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
31const Koa = require('koa')
const fs = require('fs')
const app = new Koa()
const Router = require('koa-router')
let home = new Router()
// 子路由1
home.get('/', async ( ctx )=>{
let html = `
<ul>
<li><a href="/page/helloworld">/page/helloworld</a></li>
<li><a href="/page/404">/page/404</a></li>
</ul>
`
ctx.body = html
})
// 子路由2
let page = new Router()
page.get('/404', async ( ctx )=>{
ctx.body = '404 page!'
}).get('/helloworld', async ( ctx )=>{
ctx.body = 'helloworld page!'
})
// 装载所有子路由
let router = new Router()
router.use('/', home.routes(), home.allowedMethods())
router.use('/page', page.routes(), page.allowedMethods())
// 加载路由中间件
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000, () => {
console.log('[demo] route-use-middleware is starting at port 3000')
})
请求数据获取
get请求
https://github.com/ChenShenhai/koa2-note/blob/master/demo/request/get.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22const Koa = require('koa')
const app = new Koa()
app.use( async ( ctx ) => {
let url = ctx.url
// 从上下文的request对象中获取
let request = ctx.request
let req_query = request.query
let req_querystring = request.querystring
// 从上下文中直接获取
let ctx_query = ctx.query
let ctx_querystring = ctx.querystring
ctx.body = {
url,
req_query,
req_querystring,
ctx_query,
ctx_querystring
}
})
app.listen(3000, () => {
console.log('[demo] request get is starting at port 3000')
})post请求
https://github.com/ChenShenhai/koa2-note/blob/master/demo/request/post.js1
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// 解析上下文里node原生请求的POST参数
function parsePostData( ctx ) {
return new Promise((resolve, reject) => {
try {
let postdata = "";
ctx.req.addListener('data', (data) => {
postdata += data
})
ctx.req.addListener("end",function(){
let parseData = parseQueryStr( postdata )
resolve( parseData )
})
} catch ( err ) {
reject(err)
}
})
}
// 将POST请求参数字符串解析成JSON
function parseQueryStr( queryStr ) {
let queryData = {}
let queryStrList = queryStr.split('&')
console.log( queryStrList )
for ( let [ index, queryStr ] of queryStrList.entries() ) {
let itemList = queryStr.split('=')
queryData[ itemList[0] ] = decodeURIComponent(itemList[1])
}
return queryData
}koa-bodyparser中间件
https://github.com/ChenShenhai/koa2-note/blob/master/demo/request/post-middleware.js1
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
34const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
// 使用ctx.body解析中间件
app.use(bodyParser())
app.use( async ( ctx ) => {
if ( ctx.url === '/' && ctx.method === 'GET' ) {
// 当GET请求时候返回表单页面
let html = `
<h1>koa2 request post demo</h1>
<form method="POST" action="/">
<p>userName</p>
<input name="userName" /><br/>
<p>nickName</p>
<input name="nickName" /><br/>
<p>email</p>
<input name="email" /><br/>
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if ( ctx.url === '/' && ctx.method === 'POST' ) {
// 当POST请求的时候,中间件koa-bodyparser解析POST表单里的数据,并显示出来
let postData = ctx.request.body
ctx.body = postData
} else {
// 其他请求显示404
ctx.body = '<h1>404!!! o(╯□╰)o</h1>'
}
})
app.listen(3000, () => {
console.log('[demo] request post is starting at port 3000')
})
原生koa2实现静态资源服务器
https://github.com/ChenShenhai/koa2-note/blob/master/demo/static-server/1
2
3
4
5
6
7
8
9
10
11
12├── static # 静态资源目录
│ ├── css/
│ ├── image/
│ ├── js/
│ └── index.html
├── util # 工具代码
│ ├── content.js # 读取请求内容
│ ├── dir.js # 读取目录内容
│ ├── file.js # 读取文件内容
│ ├── mimes.js # 文件类型列表
│ └── walk.js # 遍历目录内容
└── index.js # 启动入口文件
1 | const Koa = require('koa') |
koa-static 中间件
https://github.com/ChenShenhai/koa2-note/blob/master/demo/static-use-middleware/1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const Koa = require('koa')
const path = require('path')
const static = require('koa-static')
const app = new Koa()
// 静态资源目录对于相对入口文件index.js的路径
const staticPath = './static'
app.use(static(
path.join( __dirname, staticPath)
))
app.use( async ( ctx ) => {
ctx.body = 'hello world'
})
app.listen(3000, () => {
console.log('[demo] static-use-middleware is starting at port 3000')
})
koa2使用cookie
1 | const Koa = require('koa') |
koa2实现session
1 | const Koa = require('koa') |
koa2加载模板引擎
https://github.com/ChenShenhai/koa2-note/blob/master/demo/ejs/1
2
3
4├── package.json
├── index.js
└── view
└── index.ejs
1 | const Koa = require('koa') |
文件上传 busboy模块、异步上传图片
https://github.com/ChenShenhai/koa2-note/tree/master/demo/upload-async1
2
3
4
5
6
7
8
9
10
11
12.
├── index.js # 后端启动文件
├── node_modules
├── package.json
├── static # 静态资源目录
│ ├── image # 异步上传图片存储目录
│ └── js
│ └── index.js # 上传图片前端js操作
├── util
│ └── upload.js # 后端处理图片流操作
└── view
└── index.ejs
创建数据库会话
1 | const mysql = require('mysql') |
async/await封装使用mysql
- promise 封装./async-db
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
27const mysql = require('mysql')
const pool = mysql.createPool({
host : '127.0.0.1',
user : 'root',
password : '123456',
database : 'my_database'
})
let query = function( sql, values ) {
return new Promise(( resolve, reject ) => {
pool.getConnection(function(err, connection) {
if (err) {
reject( err )
} else {
connection.query(sql, values, ( err, rows) => {
if ( err ) {
reject( err )
} else {
resolve( rows )
}
connection.release()
})
}
})
})
}
module.exports = { query }
async/await 使用1
2
3
4
5
6
7
8
9
10
11const { query } = require('./async-db')
async function selectAllData( ) {
let sql = 'SELECT * FROM my_table'
let dataList = await query( sql )
return dataList
}
async function getData() {
let dataList = await selectAllData()
console.log( dataList )
}
getData()
跨域
https://github.com/ChenShenhai/koa2-note/blob/master/demo/jsonp/1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 判断是否为JSONP的请求
if ( ctx.method === 'GET' && ctx.url.split('?')[0] === '/getData.jsonp') {
// 获取jsonp的callback
let callbackName = ctx.query.callback || 'callback'
let returnData = {
success: true,
data: {
text: 'this is a jsonp api',
time: new Date().getTime(),
}
}
// jsonp的script字符串
let jsonpStr = `;${callbackName}(${JSON.stringify(returnData)})`
// 用text/javascript,让请求支持跨域获取
ctx.type = 'text/javascript'
// 输出jsonp字符串
ctx.body = jsonpStr
}
单元测试
比较出名的有mocha,karma,jasmine等
https://github.com/ChenShenhai/koa2-note/blob/master/demo/test-unit/
开发debug
https://github.com/ChenShenhai/koa2-note/blob/master/demo/start-quick/