KOA学习笔记
Posted 京东成都研究院
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KOA学习笔记相关的知识,希望对你有一定的参考价值。
KOA的简介
koa.js 是下一代的node.js框架,由Express团队开发,通过生成器(generators javascript 1.7新引入的,用于解决回调嵌套的方案),减少异步回调,提高代码的可读性和可维护性,同时改进了错误处理(Express的错误处理方式相当糟糕)。
KOA的优点
更优雅、简单、安全的中间件机制
更优雅、简单的异常处理
更优雅、简单的异步编程方式
KOA环境依赖
KOA@1 Node环境最低 v0.11.x
运行server的时候开启 –harmony (或–harmony-generators)来支持ES6的generators
node--harmony app.js
KOA@2 Node环境 node v7.6.x 来支持ES7的async函数
一如既往的hello word
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
// 等价于 http.createServer(app.callback()).listen(3000);
KOA中的上下文 Context
Koa Context 将 node 的 request和 response 对象封装在一个单独的对象里面,其为编写web 应用和 API 提供了很多有用的方法。
这些操作在 HTTP 服务器开发中经常使用,因此其被添加在上下文这一层,而不是更高层框架中,因此将迫使中间件需要重新实现这些常用方法。
context 在每个 request 请求中被创建,在中间件中作为接收器(receiver)来引用,或者通过 this 标识符来引用
app.use(function *(){
this; // is theContext
this.request; // is akoa Request
this.response;// is a koa Response
});
许多 context 的访问器和方法为了便于访问和调用,简单的委托给他们的ctx.request 和 ctx.response 所对应的等价方法, 比如说 ctx.type 和 ctx.length 代理了 response 对象中对应的方法,ctx.path 和 ctx.method 代理了 request 对象中对应的方法。
常用的API
ctx.req Node 的 request 对象。
ctx.res Node 的 response 对象。
ctx.request Koa 的 Request 对象。
ctx.response Koa 的 Response 对象。
ctx.app 应用实例引用。
ctx.cookies.get(name, [options])
ctx.cookies.set(name, value, [options])
signed: 是否要做签名
expires: cookie 有效期时间
path: cookie 的路径,默认为 /
domain: cookie 的域
secure: false 表示 cookie 通过 HTTP协议发送,true 表示 cookie 通过 HTTPS 发送。
httpOnly: true 表示 cookie 只能通过HTTP 协议发送
Koa不支持直接调用底层 res 进行响应处理
res.statusCode
res.writeHead()
res.write()
res.end()
KOA@2 对async await语法支持
functiongetSyncTime() {
returnnewPromise((resolve,reject) => {
try {
let startTime= newDate().getTime()
setTimeout(() => {
let endTime =newDate().getTime()
let data =endTime - startTime
resolve( data )
}, 500)
} catch ( err ) {
reject( err )
}
})
}
asyncfunctiongetSyncData() {
let time = awaitgetSyncTime()
let data = `endTime -startTime = ${time}`
return data
}
asyncfunctiongetData() {
let data = awaitgetSyncData()
console.log( data)
}
getData()
Chrome 提供原生支持async/await
async/await 的特点
可以让异步逻辑用同步写法实现 {:&.rollIn}
最底层的await返回需要是Promise对象
可以通过多层 async function 的同步写法代替传统的callback嵌套
koa@2的中间件写法
app.use(async (next)=> {
var start = newDate;
await next();
var ms = newDate - start;
this.set('X-Response-Time', ms + 'ms');
});
koa@1的中间件写法
app.use(function *(next){
var start = newDate;
yield next;
var ms = newDate - start;
this.set('X-Response-Time', ms + 'ms');
});
KOA中间件的执行顺序
KOA中间件的开发和使用
generator中间件开发
// generator中间件返回的应该是function* () 函数
functionlog( ctx ) {
console.log(ctx.method, ctx.header.host + ctx.url )
}
module.exports = function () {
returnfunction* ( next ) {
// 执行中间件的操作
log( this )
if ( next ){
yield next
}
}
}
generator中间件在koa@1中的使用
// generator 中间件在koa v1中可以直接use使用
const koa = require('koa') // koa v1
const loggerGenerator = require('./middleware/logger-generator')
const app = koa()
app.use(loggerGenerator())
app.use(function *() {
this.body = 'helloworld!'
})
app.listen(3000)
console.log('the server is starting at port 3000')
async中间件开发
functionlog( ctx ) {
console.log(ctx.method, ctx.header.host + ctx.url )
}
module.exports = function () {
returnfunction ( ctx, next) {
returnnewPromise( ( resolve,reject ) => {
// 执行中间件的操作
log( ctx )
resolve()
return next()
}).catch(( err ) => {
return next()
})
}
}
async 中间件在koa@2中使用
// async 中间件只能在 koa v2中使用
const Koa = require('koa') // koa v2
const loggerAsync = require('./middleware/logger-async')
const app = new Koa()
app.use(loggerAsync())
app.use(( ctx ) => {
ctx.body = 'helloworld!'
})
app.listen(3000)
console.log('the server is starting at port 3000')
路由
koa@2 原生路由实现
koa@2 GET请求
在koa中,获取GET请求数据源头是koa中request对象中的query方法或querystring方法,query返回是格式化好的参数对象,querystring返回的是请求字符串,由于ctx对request的API有直接引用的方式,所以获取GET请求数据有两个途径。
1.是从上下文中直接获取
请求对象ctx.query,返回如 { a:1, b:2 }
请求字符串 ctx.querystring,返回如 a=1&b=22.是从上下文的request对象中获取
请求对象ctx.request.query,返回如 { a:1, b:2 }
请求字符串 ctx.request.querystring,返回如 a=1&b=2
koa@2 GET请求
const 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
letreq_querystring = request.querystring
// 从上下文中直接获取
let ctx_query= ctx.query
letctx_querystring = ctx.querystring
ctx.body = {
url,
req_query,
req_querystring,
ctx_query,
ctx_querystring
}
})
app.listen(3000);
koa@2 POST请求
对于POST请求的处理,koa2没有封装获取参数的方法,需要通过解析上下文context中的原生node.js请求对象req,将POST表单数据解析成querystring(例如:a=1&b=2&c=3),再将query string 解析成JSON格式(例如:{“a”:”1”, “b”:”2”, “c”:”3”})
// 解析上下文里node原生请求的POST参数
functionparsePostData( ctx ) {
returnnewPromise((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
functionparseQueryStr( queryStr ) {
let queryData= {}
letqueryStrList = 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的模板引擎
适用于 koa 的模板引擎选择非常多,比如 jade、ejs、nunjucks、xtemplate等。
怎么选择 ? 主要考虑以下几个因素:
上手难度 xtemplate < nunjucks < ejs < jade {:&.rollIn}
功能的强大度 nunjucks > xtemplate > jade > ejs
是否支持前后端混用 jade不支持
性能考量 xtemplate 会更优秀些
jade
body
h1 Jade - node template engine
#container.col
if youAreUsingJade
p You are amazing
else
p Get on it!
ejs
<p><%=: users |first | capitalize %></p>
xtemplate
{{#if(variable===0)}}
It is true
{{/if}}
nunjucks
{% if variable== 0 %}
It is true
{% endif %}
koa@2加载模板引擎
const Koa = require('koa')
const views = require('koa-views')
const path = require('path')
const app = new Koa()
// 加载模板引擎
app.use(views(path.join(__dirname, './view'), {
extension: 'ejs'
}))
app.use( async ( ctx ) => {
let title = 'hello koa2'
await ctx.render('index', {
title,
})
})
app.listen(3000)
后记
ES6/7 带来的变革
自ES6确定和ES7的async/await开始普及,node.js的发展变得更加迅速,可以预见到JavaScript中令人“头疼”的多层嵌套回调(注意是”多层嵌套回调“)将会使用Promise + async/await的方式逐渐替代(不是完全替代,多层嵌套回调也有其特殊的应用场景)。
koa2 大势所趋的前景
基于async/await实现中间体系的koa2框架将会是是node.js web开发方向大势所趋的普及框架。基于generator/yield的koa1将会逐渐被koa2替代,毕竟使用co.js来处理generator是一种过渡的方式,虽然有其特定的应用场景,但是用async/await会更加优雅地实现同步写法。
参考
以上是关于KOA学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
《Koa.js 设计模式-学习笔记》Koa.js第二本开源电子书完结