1.koa是什么?
koa是Express的下一代基于Node.js的web框架,目前有1.x和2.0两个版本。experss是第一代最流行的框架,它对node的http模块进行了封装,但它基于es5的语法,要使用异步代码,只有一个方法:回调。如果异步嵌套层次过多,代码写起来就非常难看,随着新版Node.js开始支持ES6,Express的团队又基于ES6的generator重新编写了下一代web框架koa。
和Express相比,koa 1.0使用generator实现异步,代码看起来像同步的:
var koa = require('koa');
var app = koa();
app.use('/test', function *() {
yield doReadFile1();
var data = yield doReadFile2();
this.body = data;
});
app.listen(3000);
koa2
koa团队并没有止步于koa 1.0,他们非常超前地基于ES7开发了koa2,和koa 1相比,koa2完全使用Promise并配合async来实现异步。
koa2的代码看上去像这样:
app.use(async (ctx, next) => {
await next();
var data = await doReadFile();
ctx.response.type = 'text/plain';
ctx.response.body = data;
});
app.callback()
返回适用于 http.createServer() 方法的回调函数来处理请求。你也可以使用此回调函数将 koa 应用程序挂载到 Connect/Express 应用程序中。
我们可以对ctx操作,并设置返回内容。但是为什么要调用await next()?
原因是koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能。
middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。
此外,如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。
注意ctx对象有一些简写的方法,例如ctx.url相当于ctx.request.url,ctx.type相当于ctx.response.type
koa-router
为了处理URL,我们需要引入koa-router这个middleware,让它负责处理URL映射。
先在package.json中添加依赖项:
"koa-router": "7.0.0"
然后用npm install安装。
接下来,我们修改app.js,使用koa-router来处理URL:
const Koa = require('koa');
// 注意require('koa-router')返回的是函数:
const router = require('koa-router')();
const app = new Koa();
// log request URL:
app.use(async (ctx, next) => {
console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
await next();
});
// add url-route:
router.get('/hello/:name', async (ctx, next) => {
var name = ctx.params.name;
ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});
router.get('/', async (ctx, next) => {
ctx.response.body = '<h1>Index</h1>';
});
// add router middleware:
app.use(router.routes());
app.listen(3000);
console.log('app started at port 3000...');
注意导入koa-router的语句最后的()是函数调用:
const router = require('koa-router')();
相当于:
const fn_router = require('koa-router');
const router = fn_router();
koa-bodyparser
用post请求处理URL时,我们会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!
所以,我们又需要引入另一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。
koa-bodyparser就是用来干这个活的。
我们在package.json中添加依赖项:
"koa-bodyparser": "3.2.0"
然后使用npm install安装。
下面,修改app.js,引入koa-bodyparser:
const bodyParser = require('koa-bodyparser');
在合适的位置加上:
app.use(bodyParser());
由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上。
现在我们就可以处理post请求了。写一个简单的登录表单:
router.get('/', async (ctx, next) => {
ctx.response.body = `<h1>Index</h1>
<form action="/signin" method="post">
<p>Name: <input name="name" value="koa"></p>
<p>Password: <input name="password" type="password"></p>
<p><input type="submit" value="Submit"></p>
</form>`;
});
router.post('/signin', async (ctx, next) => {
var
name = ctx.request.body.name || '',
password = ctx.request.body.password || '';
console.log(`signin with name: ${name}, password: ${password}`);
if (name === 'koa' && password === '12345') {
ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
} else {
ctx.response.body = `<h1>Login failed!</h1>
<p><a href="/">Try again</a></p>`;
}
});
网友评论